public void UnmarshalAsSpecificType()
        {
            var jsonStr = "{\"key\":\"flag\",\"on\":false}";
            var flag    = FeatureStoreHelpers.UnmarshalJson(VersionedDataKind.Features, jsonStr);

            Assert.Equal("flag", flag.Key);
        }
        public void UnmarshalAsGeneralType()
        {
            var jsonStr             = "{\"key\":\"flag\",\"on\":false}";
            IVersionedDataKind kind = VersionedDataKind.Features;
            var flag = FeatureStoreHelpers.UnmarshalJson(kind, jsonStr);

            Assert.Equal("flag", flag.Key);
        }
        public void MarshalEntity()
        {
            var flag       = new FeatureFlagBuilder("flag").Build();
            var actualStr  = FeatureStoreHelpers.MarshalJson(flag);
            var actualJson = JsonConvert.DeserializeObject <JObject>(actualStr);

            Assert.Equal("flag", (string)actualJson.GetValue("key"));
        }
Ejemplo n.º 4
0
        public IVersionedData GetInternal(IVersionedDataKind kind, string key)
        {
            IDatabase db   = _redis.GetDatabase();
            string    json = db.HashGet(ItemsKey(kind), key);

            if (json == null)
            {
                Log.DebugFormat("[get] Key: {0} not found in \"{1}\"", key, kind.GetNamespace());
                return(null);
            }
            return(FeatureStoreHelpers.UnmarshalJson(kind, json));
        }
Ejemplo n.º 5
0
        public IDictionary <string, IVersionedData> GetAllInternal(IVersionedDataKind kind)
        {
            IDatabase db = _redis.GetDatabase();

            HashEntry[] allEntries = db.HashGetAll(ItemsKey(kind));
            Dictionary <string, IVersionedData> result = new Dictionary <string, IVersionedData>();

            foreach (HashEntry entry in allEntries)
            {
                IVersionedData item = FeatureStoreHelpers.UnmarshalJson(kind, entry.Value);
                result[item.Key] = item;
            }
            return(result);
        }
Ejemplo n.º 6
0
        public IVersionedData UpsertInternal(IVersionedDataKind kind, IVersionedData newItem)
        {
            IDatabase db      = _redis.GetDatabase();
            string    baseKey = ItemsKey(kind);

            while (true)
            {
                string oldJson;
                try
                {
                    oldJson = db.HashGet(baseKey, newItem.Key);
                }
                catch (RedisTimeoutException e)
                {
                    Log.ErrorFormat("Timeout in update when reading {0} from {1}: {2}", newItem.Key, baseKey, e.ToString());
                    throw;
                }
                IVersionedData oldItem    = (oldJson == null) ? null : FeatureStoreHelpers.UnmarshalJson(kind, oldJson);
                int            oldVersion = (oldJson == null) ? -1 : oldItem.Version;
                if (oldVersion >= newItem.Version)
                {
                    Log.DebugFormat("Attempted to {0} key: {1} version: {2} with a version that is" +
                                    " the same or older: {3} in \"{4}\"",
                                    newItem.Deleted ? "delete" : "update",
                                    newItem.Key, oldVersion, newItem.Version, kind.GetNamespace());
                    return(oldItem);
                }

                // This hook is used only in unit tests
                _updateHook?.Invoke();

                // Note that transactions work a bit differently in StackExchange.Redis than in other
                // Redis clients. The same Redis connection is shared across all threads, so it can't
                // set a WATCH at the moment we start the transaction. Instead, it saves up all of
                // the actions we send during the transaction, and replays them all within a MULTI
                // when the transaction. AddCondition() is this client's way of doing a WATCH, and it
                // can only refer to the whole value, not to a JSON property of the value; that's why
                // we kept track of the whole value in "oldJson".
                ITransaction txn = db.CreateTransaction();
                txn.AddCondition(oldJson == null ? Condition.HashNotExists(baseKey, newItem.Key) :
                                 Condition.HashEqual(baseKey, newItem.Key, oldJson));

                txn.HashSetAsync(baseKey, newItem.Key, JsonConvert.SerializeObject(newItem));

                try
                {
                    bool success = txn.Execute();
                    if (!success)
                    {
                        // The watch was triggered, we should retry
                        Log.Debug("Concurrent modification detected, retrying");
                        continue;
                    }
                }
                catch (RedisTimeoutException e)
                {
                    Log.ErrorFormat("Timeout on update of {0} in {1}: {2}", newItem.Key, baseKey, e.ToString());
                    throw;
                }
                return(newItem);
            }
        }