Skip to main content

No project description provided

Project description

rust_decider

Rust implementation of bucketing, targeting, overrides, and dynamic config logic.

Usage

class Decider

A class used to expose these APIs:

  • choose(
       feature_name: str,
       context: Mapping[str, JsonValue]
    ) -> Decision
    
  • choose_all(
       context: Mapping[str, JsonValue],
       bucketing_field_filter: Optional[str] = None
    ) -> Dict[str, Decision]
    

(dynamic configurations)

  • get_bool(
      feature_name: str,
      context: Mapping[str, JsonValue],
    ) -> bool
    
  • get_int(
      feature_name: str,
      context: Mapping[str, JsonValue],
    ) -> int
    
  • get_float(
      feature_name: str,
      context: Mapping[str, JsonValue],
    ) -> float
    
  • get_string(
      feature_name: str,
      context: Mapping[str, JsonValue],
    ) -> str
    
  • get_map(
      feature_name: str,
      context: Mapping[str, JsonValue],
    ) -> Dict[str, Any]
    
  • all_values(
       context: Mapping[str, JsonValue],
    ) -> Dict[str, Any]
    

misc:

  • get_feature(
      feature_name: str,
    ) -> Feature
    

choose() examples:

from rust_decider import Decider
from rust_decider import DeciderException
from rust_decider import FeatureNotFoundException
from rust_decider import DeciderInitException
from rust_decider import PartialLoadException
from rust_decider import ValueTypeMismatchException

# initialize Decider instance
try:
    decider = Decider("../cfg.json")
except PartialLoadException as e:
    # log errors of misconfigured features
    print(f"{e.args[0]}: {e.args[2]}")

    # use partially initialized Decider instance
    decider = e.args[1]
except DeciderInitException as e:
    print(e)

# get a Decision for a feature via choose()
try:
    decision = decider.choose(feature_name="exp_1", context={"user_id": "3", "app_name": "ios"})
except DeciderException as e:
    print(e)

assert dict(decision) == {
    "variant": "variant_0",
    "value": None,
    "feature_id": 3246,
    "feature_name": "exp_1",
    "feature_version": 2,
    "events": [
      "0::::3246::::exp_1::::2::::variant_0::::3::::user_id::::37173982::::2147483648::::test"
    ]
}

# `user_id` targeting not satisfied so "variant" is `None` in the returned Decision
try:
    decision = decider.choose(feature_name="exp_1", context={"user_id": "1"})
except DeciderException as e:
    print(e)

assert dict(decision) == {
  "variant": None,
  "value": None,
  "feature_id": 3246,
  "feature_name": "exp_1",
  "feature_version": 2,
  "events": []
}

# handle "feature not found" exception
# (`FeatureNotFoundException` is a subclass of `DeciderException`)
try:
    decision = decider.choose(feature_name="not_here", context={"user_id": "1"})
except FeatureNotFoundException as e:
  print("handle feature not found exception:")
  print(e)
except DeciderException as e:
    print(e)

choose_all() examples:

# `decider` initialized same as above
decisions = decider.choose_all(context={"user_id": "3", "app_name": "ios"}, bucketing_field_filter="user_id")

assert dict(decisions["exp_67"]) == {
  "variant": "variant_0",
  "value": None,
  "feature_id": 3125,
  "feature_name": "exp_67",
  "feature_version": 4,
  "events": [
    "0::::3125::::exp_67::::4::::variant_0::::3::::user_id::::37173982::::2147483648::::test"
  ]
}

Dynamic Configurations + misc. examples:

# `decider` initialized same as above
try:
    dc_bool = decider.get_bool("dc_bool", context={})
    dc_int = decider.get_int("dc_int", context={})
    dc_float = decider.get_float("dc_float", context={})
    dc_string = decider.get_string("dc_string", context={})
    dc_map = decider.get_map("dc_map", context={})

    feature = decider.get_feature("dc_map")
except FeatureNotFoundException as e:
    print("handle feature not found exception:")
    print(e)
except ValueTypeMismatchException as e:
    print("handle type mismatch:")
    print(e)
except DeciderException as e:
    print(e)

assert dc_bool == True
assert dc_int == 99
assert dc_float == 3.0
assert dc_string == "some_string"
assert dc_map == {
  "v": {
      "nested_map": {
          "w": False,
          "x": 1,
          "y": "some_string",
          "z": 3.0
      }
  },
  "w": False,
  "x": 1,
  "y": "some_string",
  "z": 3.0
}

assert dict(feature) == {
  "id": 3393,
  "name": "dc_bool",
  "version": 2,
  "bucket_val": '',
  "start_ts": 0,
  "stop_ts": 0,
  "owner": "test",
  "emit_event": False
}

Dynamic Configuration all_values() example:

# `decider` initialized same as above
decisions = decider.all_values(context={})

assert decisions["dc_int"] == 99

python bindings used in Decider class

import rust_decider

# Init decider
decider = rust_decider.init("darkmode overrides targeting holdout mutex_group fractional_availability value", "../cfg.json")

# Bucketing needs a context
ctx = rust_decider.make_ctx({"user_id": "7"})

# Get a decision
choice = decider.choose("exp_1", ctx)
assert choice.err() is None # check for errors
choice.decision() # get the variant

# Get a dynamic config value
dc = decider.get_map("dc_map", ctx) # fetch a map DC
assert dc.err() is None # check for errors
dc.val() # get the actual map itself

Development

Updating package with latest src/lib.rs changes

# In a virtualenv, python >= 3.7
$ cd decider-py
$ pip install -r requirements-dev.txt
$ maturin develop

Running tests

$ pytest decider-py/test/

Publishing

Use conventional commit format in PR titles to trigger releases via release-please task in drone pipeline.

  • chore: & build: commits don't trigger releases (used for changes like updating config files or documentation)
  • fix: bumps the patch version
  • feat: bumps the minor version
  • feat!: bumps the major version

Formatting / Linting

$ cargo fmt    --manifest-path decider-py/test/Cargo.toml
$ cargo clippy --manifest-path decider-py/test/Cargo.toml

Project details


Release history Release notifications | RSS feed

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

reddit_decider-1.5.6.tar.gz (60.7 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

reddit_decider-1.5.6-cp37-abi3-musllinux_1_1_x86_64.whl (432.5 kB view details)

Uploaded CPython 3.7+musllinux: musl 1.1+ x86-64

reddit_decider-1.5.6-cp37-abi3-manylinux_2_28_x86_64.whl (399.3 kB view details)

Uploaded CPython 3.7+manylinux: glibc 2.28+ x86-64

reddit_decider-1.5.6-cp37-abi3-macosx_11_0_arm64.whl (356.8 kB view details)

Uploaded CPython 3.7+macOS 11.0+ ARM64

reddit_decider-1.5.6-cp37-abi3-macosx_10_7_x86_64.whl (366.8 kB view details)

Uploaded CPython 3.7+macOS 10.7+ x86-64

File details

Details for the file reddit_decider-1.5.6.tar.gz.

File metadata

  • Download URL: reddit_decider-1.5.6.tar.gz
  • Upload date:
  • Size: 60.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.13.0 pkginfo/1.5.0.1 requests/2.21.0 setuptools/40.8.0 requests-toolbelt/0.9.1 tqdm/4.31.1 CPython/3.6.8

File hashes

Hashes for reddit_decider-1.5.6.tar.gz
Algorithm Hash digest
SHA256 992a7ddfcaf03636b449e5b1f369cc8c54fc6bb5a85e6a7cd0df012166178e26
MD5 a670dddeea031c89a34de60e59f66569
BLAKE2b-256 bf39d9d2328956095e3feee9caa86affdec21370c2004cd9c8e9d2f2e11610fb

See more details on using hashes here.

File details

Details for the file reddit_decider-1.5.6-cp37-abi3-musllinux_1_1_x86_64.whl.

File metadata

  • Download URL: reddit_decider-1.5.6-cp37-abi3-musllinux_1_1_x86_64.whl
  • Upload date:
  • Size: 432.5 kB
  • Tags: CPython 3.7+, musllinux: musl 1.1+ x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.13.0 pkginfo/1.5.0.1 requests/2.21.0 setuptools/40.8.0 requests-toolbelt/0.9.1 tqdm/4.31.1 CPython/3.6.8

File hashes

Hashes for reddit_decider-1.5.6-cp37-abi3-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 e2299f707db6f71c88fa545e647460efb83deab8c7c619d0b66466e7b9a07df2
MD5 871d0c406b93c20d63ccc11e85f6b2c3
BLAKE2b-256 ab6d5bf41a3865f450ec7797764589da0d08a84309bb4e50f874df3445b98193

See more details on using hashes here.

File details

Details for the file reddit_decider-1.5.6-cp37-abi3-manylinux_2_28_x86_64.whl.

File metadata

  • Download URL: reddit_decider-1.5.6-cp37-abi3-manylinux_2_28_x86_64.whl
  • Upload date:
  • Size: 399.3 kB
  • Tags: CPython 3.7+, manylinux: glibc 2.28+ x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.13.0 pkginfo/1.5.0.1 requests/2.21.0 setuptools/40.8.0 requests-toolbelt/0.9.1 tqdm/4.31.1 CPython/3.6.8

File hashes

Hashes for reddit_decider-1.5.6-cp37-abi3-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 8197c9d6cafa6f434dbb0e938ac27673ddfac36e310ba8365e5122f95c8503b9
MD5 203fc439edc456e2b7c61927ebc19939
BLAKE2b-256 a6fb42d400bdb230de5fab2b0ecbf44b3fe959991ccebba677f7688a05249f7e

See more details on using hashes here.

File details

Details for the file reddit_decider-1.5.6-cp37-abi3-macosx_11_0_arm64.whl.

File metadata

  • Download URL: reddit_decider-1.5.6-cp37-abi3-macosx_11_0_arm64.whl
  • Upload date:
  • Size: 356.8 kB
  • Tags: CPython 3.7+, macOS 11.0+ ARM64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.13.0 pkginfo/1.5.0.1 requests/2.21.0 setuptools/40.8.0 requests-toolbelt/0.9.1 tqdm/4.31.1 CPython/3.6.8

File hashes

Hashes for reddit_decider-1.5.6-cp37-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 02bc1fa425688b4bfc9c32bdda98eaeb7e2aeb6f3c4f72d32570ce863929b551
MD5 aebc4a0baeb2c9db8cacadf4b145e9ee
BLAKE2b-256 0537736b4b2642f372fb5bdd2d06041c7005b7ed6cb3aef6ce644b2d9ded2cec

See more details on using hashes here.

File details

Details for the file reddit_decider-1.5.6-cp37-abi3-macosx_10_7_x86_64.whl.

File metadata

  • Download URL: reddit_decider-1.5.6-cp37-abi3-macosx_10_7_x86_64.whl
  • Upload date:
  • Size: 366.8 kB
  • Tags: CPython 3.7+, macOS 10.7+ x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.13.0 pkginfo/1.5.0.1 requests/2.21.0 setuptools/40.8.0 requests-toolbelt/0.9.1 tqdm/4.31.1 CPython/3.6.8

File hashes

Hashes for reddit_decider-1.5.6-cp37-abi3-macosx_10_7_x86_64.whl
Algorithm Hash digest
SHA256 a8f4f48e574c46a85262f0d8b1e6611c7d5a6c5dac6488c962e762528286bb28
MD5 bbd712e3cf173f370bc8ae6468809260
BLAKE2b-256 c533afaf42a7ecf4e228e1ae3061b29a42e1fcc84f69692b30ccf79cef3ca0ab

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page