Beispiel #1
0
class RedisFeatureStore(FeatureStore):
    """A Redis-backed implementation of :class:`ldclient.interfaces.FeatureStore`.

    .. deprecated:: 6.7.0
      This module and this implementation class are deprecated and may be changed or removed in the future.
      Please use :func:`ldclient.integrations.Redis.new_feature_store()`.
    """
    def __init__(self,
                 url='redis://localhost:6379/0',
                 prefix='launchdarkly',
                 max_connections=16,
                 expiration=15,
                 capacity=1000):
        self.core = _RedisFeatureStoreCore(url, prefix, max_connections)  # exposed for testing
        self._wrapper = CachingStoreWrapper(self.core, CacheConfig(expiration=expiration, capacity=capacity))

    def get(self, kind, key, callback = lambda x: x):
        return self._wrapper.get(kind, key, callback)
    
    def all(self, kind, callback):
        return self._wrapper.all(kind, callback)
    
    def init(self, all_data):
        return self._wrapper.init(all_data)
    
    def upsert(self, kind, item):
        return self._wrapper.upsert(kind, item)
    
    def delete(self, kind, key, version):
        return self._wrapper.delete(kind, key, version)
    
    @property
    def initialized(self):
        return self._wrapper.initialized
Beispiel #2
0
    def new_feature_store(url='redis://localhost:6379/0',
                          prefix='launchdarkly',
                          max_connections=16,
                          caching=CacheConfig.default()):
        """Creates a Redis-backed implementation of :class:`ldclient.interfaces.FeatureStore`.
        For more details about how and why you can use a persistent feature store, see the
        `SDK reference guide <https://docs.launchdarkly.com/v2.0/docs/using-a-persistent-feature-store>`_.

        To use this method, you must first install the ``redis`` package. Then, put the object
        returned by this method into the ``feature_store`` property of your client configuration
        (:class:`ldclient.config.Config`).
        ::

            from ldclient.integrations import Redis
            store = Redis.new_feature_store()
            config = Config(feature_store=store)

        :param string url: the URL of the Redis host; defaults to ``DEFAULT_URL``
        :param string prefix: a namespace prefix to be prepended to all Redis keys; defaults to
          ``DEFAULT_PREFIX``
        :param int max_connections: the maximum number of Redis connections to keep in the
          connection pool; defaults to ``DEFAULT_MAX_CONNECTIONS``
        :param CacheConfig caching: specifies whether local caching should be enabled and if so,
          sets the cache properties; defaults to :func:`ldclient.feature_store.CacheConfig.default()`
        """
        core = _RedisFeatureStoreCore(url, prefix, max_connections)
        wrapper = CachingStoreWrapper(core, caching)
        wrapper.core = core  # exposed for testing
        return wrapper
    def new_feature_store(url='redis://localhost:6379/0',
                          prefix='launchdarkly',
                          max_connections=16,
                          caching=CacheConfig.default()):
        """Creates a Redis-backed implementation of :class:`ldclient.interfaces.FeatureStore`.
        For more details about how and why you can use a persistent feature store, see the
        `SDK reference guide <https://docs.launchdarkly.com/v2.0/docs/using-a-persistent-feature-store>`_.

        To use this method, you must first install the ``redis`` package. Then, put the object
        returned by this method into the ``feature_store`` property of your client configuration
        (:class:`ldclient.config.Config`).
        ::

            from ldclient.integrations import Redis
            store = Redis.new_feature_store()
            config = Config(feature_store=store)

        :param string url: the URL of the Redis host; defaults to ``DEFAULT_URL``
        :param string prefix: a namespace prefix to be prepended to all Redis keys; defaults to
          ``DEFAULT_PREFIX``
        :param int max_connections: the maximum number of Redis connections to keep in the
          connection pool; defaults to ``DEFAULT_MAX_CONNECTIONS``
        :param CacheConfig caching: specifies whether local caching should be enabled and if so,
          sets the cache properties; defaults to :func:`ldclient.feature_store.CacheConfig.default()`
        """
        core = _RedisFeatureStoreCore(url, prefix, max_connections)
        wrapper = CachingStoreWrapper(core, caching)
        wrapper.core = core  # exposed for testing
        return wrapper
Beispiel #4
0
 def __init__(self,
              url='redis://localhost:6379/0',
              prefix='launchdarkly',
              max_connections=16,
              expiration=15,
              capacity=1000):
     self.core = _RedisFeatureStoreCore(url, prefix, max_connections)  # exposed for testing
     self._wrapper = CachingStoreWrapper(self.core, CacheConfig(expiration=expiration, capacity=capacity))
Beispiel #5
0
    def new_feature_store(table_name,
                          prefix=None,
                          dynamodb_opts={},
                          caching=CacheConfig.default()):
        """Creates a DynamoDB-backed implementation of :class:`ldclient.interfaces.FeatureStore`.
        For more details about how and why you can use a persistent feature store, see the
        `SDK reference guide <https://docs.launchdarkly.com/v2.0/docs/using-a-persistent-feature-store>`_.

        To use this method, you must first install the ``boto3`` package containing the AWS SDK gems.
        Then, put the object returned by this method into the ``feature_store`` property of your
        client configuration (:class:`ldclient.config.Config`).
        ::

            from ldclient.integrations import DynamoDB
            store = DynamoDB.new_feature_store("my-table-name")
            config = Config(feature_store=store)

        Note that the DynamoDB table must already exist; the LaunchDarkly SDK does not create the table
        automatically, because it has no way of knowing what additional properties (such as permissions
        and throughput) you would want it to have. The table must have a partition key called
        "namespace" and a sort key called "key", both with a string type.

        By default, the DynamoDB client will try to get your AWS credentials and region name from
        environment variables and/or local configuration files, as described in the AWS SDK documentation.
        You may also pass configuration settings in ``dynamodb_opts``.

        :param string table_name: the name of an existing DynamoDB table
        :param string prefix: an optional namespace prefix to be prepended to all DynamoDB keys
        :param dict dynamodb_opts: optional parameters for configuring the DynamoDB client, as defined in
          the `boto3 API <https://boto3.amazonaws.com/v1/documentation/api/latest/reference/core/session.html#boto3.session.Session.client>`_
        :param CacheConfig caching: specifies whether local caching should be enabled and if so,
          sets the cache properties; defaults to :func:`ldclient.feature_store.CacheConfig.default()`
        """
        core = _DynamoDBFeatureStoreCore(table_name, prefix, dynamodb_opts)
        return CachingStoreWrapper(core, caching)
Beispiel #6
0
    def new_feature_store(host=None,
                          port=None,
                          prefix=None,
                          consul_opts=None,
                          caching=CacheConfig.default()):
        """Creates a Consul-backed implementation of :class:`ldclient.interfaces.FeatureStore`.
        For more details about how and why you can use a persistent feature store, see the
        `SDK reference guide <https://docs.launchdarkly.com/v2.0/docs/using-a-persistent-feature-store>`_.

        To use this method, you must first install the ``python-consul`` package. Then, put the object
        returned by this method into the ``feature_store`` property of your client configuration
        (:class:`ldclient.config.Config`).
        ::

            from ldclient.integrations import Consul
            store = Consul.new_feature_store()
            config = Config(feature_store=store)

        Note that ``python-consul`` is not available for Python 3.3 or 3.4, so this feature cannot be
        used in those Python versions.

        :param string host: hostname of the Consul server (uses ``localhost`` if omitted)
        :param int port: port of the Consul server (uses 8500 if omitted)
        :param string prefix: a namespace prefix to be prepended to all Consul keys
        :param dict consul_opts: optional parameters for configuring the Consul client, if you need
          to set any of them besides host and port, as defined in the
          `python-consul API <https://python-consul.readthedocs.io/en/latest/#consul>`_
        :param CacheConfig caching: specifies whether local caching should be enabled and if so,
          sets the cache properties; defaults to :func:`ldclient.feature_store.CacheConfig.default()`
        """
        core = _ConsulFeatureStoreCore(host, port, prefix, consul_opts)
        return CachingStoreWrapper(core, caching)
Beispiel #7
0
    def test_cached_initialized_can_cache_false_result(self):
        core = MockCore()
        wrapper = CachingStoreWrapper(core, CacheConfig(expiration=0.2))  # use a shorter cache TTL for this test

        assert wrapper.initialized is False
        assert core.inited_query_count == 1

        core.inited = True
        assert wrapper.initialized is False
        assert core.inited_query_count == 1

        sleep(0.5)

        assert wrapper.initialized is True
        assert core.inited_query_count == 2

        # From this point on it should remain true and the method should not be called
        assert wrapper.initialized is True
        assert core.inited_query_count == 2
def test_create_diagnostic_config_custom():
    test_store = CachingStoreWrapper(_TestStoreForDiagnostics(),
                                     CacheConfig.default())
    test_config = Config("SDK_KEY",
                         base_uri='https://test.com',
                         events_uri='https://test.com',
                         events_max_pending=10,
                         flush_interval=1,
                         stream_uri='https://test.com',
                         stream=False,
                         poll_interval=60,
                         use_ldd=True,
                         feature_store=test_store,
                         all_attributes_private=True,
                         user_keys_capacity=10,
                         user_keys_flush_interval=60,
                         inline_users_in_events=True,
                         http=HTTPConfig(http_proxy='proxy',
                                         read_timeout=1,
                                         connect_timeout=1),
                         diagnostic_recording_interval=60)
    diag_config = _create_diagnostic_config_object(test_config)

    assert len(diag_config) == 17
    assert diag_config['customBaseURI'] is True
    assert diag_config['customEventsURI'] is True
    assert diag_config['customStreamURI'] is True
    assert diag_config['eventsCapacity'] == 10
    assert diag_config['connectTimeoutMillis'] == 1000
    assert diag_config['socketTimeoutMillis'] == 1000
    assert diag_config['eventsFlushIntervalMillis'] == 1000
    assert diag_config['usingProxy'] is True
    assert diag_config['streamingDisabled'] is True
    assert diag_config['usingRelayDaemon'] is True
    assert diag_config['allAttributesPrivate'] is True
    assert diag_config['pollingIntervalMillis'] == 60000
    assert diag_config['userKeysCapacity'] == 10
    assert diag_config['userKeysFlushIntervalMillis'] == 60000
    assert diag_config['inlineUsersInEvents'] is True
    assert diag_config['diagnosticRecordingIntervalMillis'] == 60000
    assert diag_config['dataStoreType'] == 'MyFavoriteStore'
Beispiel #9
0
def make_wrapper(core, cached):
    return CachingStoreWrapper(core, CacheConfig(expiration=30) if cached else CacheConfig.disabled())