예제 #1
0
        protected virtual async Task Write(ITurnContext context)
        {
            StoreItems changes = new StoreItems();

            var state = context.Services.Get <StateT>(this._propertyName);

            if (state == null)
            {
                state = new StateT();
            }
            var key = _keyDelegate(context);

            changes[key] = state;

            if (this._settings.LastWriterWins)
            {
                foreach (var item in changes)
                {
                    if (item.Value is IStoreItem valueStoreItem)
                    {
                        valueStoreItem.eTag = "*";
                    }
                }
            }

            await _storage.Write(changes).ConfigureAwait(false);
        }
예제 #2
0
        /// <summary>
        /// Storage extension to Read as strong typed StoreItem objects
        /// </summary>
        /// <typeparam name="StoreItemT"></typeparam>
        /// <param name="storage"></param>
        /// <param name="keys"></param>
        /// <returns></returns>
        public static async Task <StoreItems <StoreItemT> > Read <StoreItemT>(this IStorage storage, params string[] keys) where StoreItemT : class
        {
            var storeItems = await storage.Read(keys).ConfigureAwait(false);

            var newResults = new StoreItems <StoreItemT>();

            foreach (var kv in storeItems)
            {
                newResults[kv.Key] = kv.Value as StoreItemT;
            }
            return(newResults);
        }
예제 #3
0
        public async Task <StoreItems> Read(string[] keys)
        {
            var storeItems = new StoreItems();

            foreach (var key in keys)
            {
                var item = await ReadIStoreItem(key).ConfigureAwait(false);

                if (item != null)
                {
                    storeItems[key] = item;
                }
            }
            return(storeItems);
        }
예제 #4
0
        public Task <StoreItems> Read(string[] keys)
        {
            var storeItems = new StoreItems();

            lock (_syncroot)
            {
                foreach (var key in keys)
                {
                    if (_memory.TryGetValue(key, out object value))
                    {
                        if (value != null)
                        {
                            storeItems[key] = FlexObject.Clone(value);
                        }
                        else
                        {
                            storeItems[key] = null;
                        }
                    }
                }
            }
            return(Task.FromResult(storeItems));
        }
예제 #5
0
        public Task Write(StoreItems changes)
        {
            lock (_syncroot)
            {
                foreach (var change in changes)
                {
                    object newValue = change.Value;
                    object oldValue = null;

                    if (_memory.TryGetValue(change.Key, out object x))
                    {
                        oldValue = x;
                    }

                    IStoreItem newStoreItem = newValue as IStoreItem;
                    IStoreItem oldStoreItem = oldValue as IStoreItem;
                    if (oldValue == null ||
                        newStoreItem?.eTag == "*" ||
                        oldStoreItem?.eTag == newStoreItem?.eTag)
                    {
                        // clone and set etag
                        newValue     = FlexObject.Clone(newValue);
                        newStoreItem = newValue as IStoreItem;
                        if (newStoreItem != null)
                        {
                            newStoreItem.eTag = (_eTag++).ToString();
                        }
                        _memory[change.Key] = newValue;
                    }
                    else
                    {
                        throw new Exception("etag conflict");
                    }
                }
            }
            return(Task.CompletedTask);
        }
예제 #6
0
 public DictionaryStorage(StoreItems dictionary = null)
 {
     _memory = dictionary ?? new StoreItems();
 }
예제 #7
0
        public async Task Write(StoreItems changes)
        {
            // Similar to the Read method, the funky threading in here is due to
            // concurrency and async methods.
            //
            // When this method is called, it may happen (in parallel) from any number of
            // thread.
            //
            // If an operation is in progress, the Open will fail with an
            // IOException. If this happens,the best thing to do is simply wait a moment
            // and retry. The Retry MUST go through the eTag processing again.
            //
            // Alternate approach in here would be to use a SemaphoreSlim and use the async/await
            // constructs.

            foreach (var change in changes)
            {
                DateTime start = DateTime.UtcNow;
                while (true)
                {
                    try
                    {
                        object newValue = change.Value;
                        object oldValue = await this.ReadIStoreItem(change.Key).ConfigureAwait(false);

                        IStoreItem newStoreItem = newValue as IStoreItem;
                        IStoreItem oldStoreItem = oldValue as IStoreItem;
                        if (oldValue == null ||
                            newStoreItem?.eTag == "*" ||
                            oldStoreItem?.eTag == newStoreItem?.eTag)
                        {
                            string key    = SanitizeKey(change.Key);
                            string path   = Path.Combine(this.folder, key);
                            var    oldTag = newStoreItem?.eTag;
                            if (newStoreItem != null)
                            {
                                newStoreItem.eTag = Guid.NewGuid().ToString("n");
                            }
                            var json = JsonConvert.SerializeObject(newValue, serializationSettings);
                            if (newStoreItem != null)
                            {
                                newStoreItem.eTag = oldTag;
                            }
                            using (TextWriter file = new StreamWriter(path))
                            {
                                await file.WriteAsync(json).ConfigureAwait(false);

                                break;
                            }
                        }
                        else
                        {
                            throw new Exception($"etag conflict key={change}");
                        }
                    }
                    catch (IOException)
                    {
                        if ((DateTime.UtcNow - start).TotalSeconds < 5)
                        {
                            await Task.Delay(0).ConfigureAwait(false);
                        }
                        else
                        {
                            throw;
                        }
                    }
                }
            }
        }