Пример #1
0
        async Task <BotData> IBotDataStore <BotData> .LoadAsync(BotDataKey key, BotStoreType botStoreType, CancellationToken cancellationToken)
        {
            BotData botData;

            switch (botStoreType)
            {
            case BotStoreType.BotConversationData:
                botData = await stateClient.BotState.GetConversationDataAsync(key.ChannelId, key.ConversationId, cancellationToken);

                break;

            case BotStoreType.BotUserData:
                botData = await stateClient.BotState.GetUserDataAsync(key.ChannelId, key.UserId, cancellationToken);

                break;

            case BotStoreType.BotPrivateConversationData:
                botData = await stateClient.BotState.GetPrivateConversationDataAsync(key.ChannelId, key.ConversationId, key.UserId, cancellationToken);

                break;

            default:
                throw new ArgumentException($"{botStoreType} is not a valid store type!");
            }
            return(botData);
        }
Пример #2
0
        async Task <object> IBotDataStore <object> .LoadAsync(BotDataKey key, BotStoreType botStoreType, CancellationToken cancellationToken)
        {
            DataEntry entry;
            object    obj = null;

            if (!cache.TryGetValue(key, out entry))
            {
                entry      = new DataEntry();
                cache[key] = entry;

                BotData value = await inner.LoadAsync(key, botStoreType, cancellationToken);

                if (value?.Data != null)
                {
                    obj = value.Data;
                }

                SetValue(entry, botStoreType, obj);
                return(obj);
            }
            else
            {
                switch (botStoreType)
                {
                case BotStoreType.BotConversationData:
                    if (entry.BotConversationData != null)
                    {
                        obj = entry.BotConversationData;
                    }
                    break;

                case BotStoreType.BotPrivateConversationData:
                    if (entry.BotPrivateConversationData != null)
                    {
                        obj = entry.BotPrivateConversationData;
                    }
                    break;

                case BotStoreType.BotUserData:
                    if (entry.BotUserData != null)
                    {
                        obj = entry.BotUserData;
                    }
                    break;
                }

                if (obj == null)
                {
                    BotData value = await inner.LoadAsync(key, botStoreType, cancellationToken);

                    if (value?.Data != null)
                    {
                        obj = value.Data;
                        SetValue(entry, botStoreType, obj);
                    }
                }

                return(obj);
            }
        }
Пример #3
0
        public Task SaveAsync(BotDataKey key, BotStoreType botStoreType, object value)
        {
            try
            {
                if (!ValidateKey(key))
                {
                    throw new ArgumentException("Invalid bot data key!");
                }

                switch (botStoreType)
                {
                case BotStoreType.BotConversationData:
                    message.BotConversationData = value;
                    break;

                case BotStoreType.BotPerUserInConversationData:
                    message.BotPerUserInConversationData = value;
                    break;

                case BotStoreType.BotUserData:
                    message.BotUserData = value;
                    break;

                default:
                    throw new ArgumentException($"key {botStoreType} is not supported by this message store");
                }

                return(Task.FromResult(Type.Missing));
            }
            catch (Exception e)
            {
                return(Task.FromException(e));
            }
        }
Пример #4
0
        public async Task <T> LoadAsync <T>(BotDataKey key, BotStoreType botStoreType)
        {
            DataEntry entry;
            T         obj = default(T);

            if (!cache.TryGetValue(key, out entry))
            {
                entry      = new DataEntry();
                cache[key] = entry;

                string value;

                if (store.TryGetValue(GetKey(key, botStoreType), out value))
                {
                    obj = (T)JsonConvert.DeserializeObject(value);
                }

                SetValue(entry, botStoreType, obj);
                return(obj);
            }
            else
            {
                switch (botStoreType)
                {
                case BotStoreType.BotConversationData:
                    if (entry.BotConversationData != null)
                    {
                        obj = (T)entry.BotConversationData;
                    }
                    break;

                case BotStoreType.BotPerUserInConversationData:
                    if (entry.BotPerUserInConversationData != null)
                    {
                        obj = (T)entry.BotPerUserInConversationData;
                    }
                    break;

                case BotStoreType.BotUserData:
                    if (entry.BotUserData != null)
                    {
                        obj = (T)entry.BotUserData;
                    }
                    break;
                }

                if (obj == null)
                {
                    string value;
                    if (store.TryGetValue(GetKey(key, botStoreType), out value))
                    {
                        obj = (T)JsonConvert.DeserializeObject(value);
                        SetValue(entry, botStoreType, obj);
                    }
                }

                return(obj);
            }
        }
Пример #5
0
        async Task <BotData> IBotDataStore <BotData> .LoadAsync(BotDataKey key, BotStoreType botStoreType, CancellationToken cancellationToken)
        {
            string serializedData;

            serializedData = store.GetOrAdd(GetKey(key, botStoreType),
                                            dictionaryKey => Serialize(new BotData {
                ETag = DateTime.UtcNow.ToString()
            }));
            return(Deserialize(serializedData));
        }
Пример #6
0
        public async Task SaveAsync(BotDataKey key, BotStoreType botStoreType, object value)
        {
            DataEntry entry;

            if (!cache.TryGetValue(key, out entry))
            {
                entry      = new DataEntry();
                cache[key] = entry;
            }

            SetValue(entry, botStoreType, value);
        }
Пример #7
0
        async Task IBotDataStore <object> .SaveAsync(BotDataKey key, BotStoreType botStoreType, object value, CancellationToken cancellationToken)
        {
            DataEntry entry;

            if (!cache.TryGetValue(key, out entry))
            {
                entry      = new DataEntry();
                cache[key] = entry;
            }

            SetValue(entry, botStoreType, value);
        }
Пример #8
0
        async Task IBotDataStore <BotData> .SaveAsync(BotDataKey key, BotStoreType botStoreType, BotData value, CancellationToken cancellationToken)
        {
            CacheEntry entry;

            if (!cache.TryGetValue(key, out entry))
            {
                entry = new CacheEntry();
                cache.Add(key, entry);
            }

            SetCachedValue(entry, botStoreType, value);
        }
Пример #9
0
        public async Task <bool> FlushAsync(BotDataKey key)
        {
            DataEntry entry = default(DataEntry);

            if (cache.TryRemove(key, out entry))
            {
                this.Save(key, entry);
                return(true);
            }
            else
            {
                return(false);
            }
        }
Пример #10
0
 async Task IBotDataStore <BotData> .SaveAsync(BotDataKey key, BotStoreType botStoreType, BotData botData, CancellationToken cancellationToken)
 {
     lock (locks[botStoreType])
     {
         store.AddOrUpdate(GetKey(key, botStoreType), JsonConvert.SerializeObject(botData), (dictionaryKey, value) =>
         {
             if (botData.ETag != "*" && JsonConvert.DeserializeObject <BotData>(value).ETag != botData.ETag)
             {
                 throw new HttpException((int)HttpStatusCode.PreconditionFailed, "Inconsistent SaveAsync based on Etag!");
             }
             botData.ETag = DateTime.UtcNow.ToString();
             return(Serialize(botData));
         });
     }
 }
Пример #11
0
        async Task <bool> IBotDataStore <object> .FlushAsync(BotDataKey key, CancellationToken cancellationToken)
        {
            DataEntry entry = default(DataEntry);

            if (cache.TryGetValue(key, out entry))
            {
                cache.Remove(key);
                await this.Save(key, entry, cancellationToken);

                return(true);
            }
            else
            {
                return(false);
            }
        }
Пример #12
0
        private async Task Save(BotDataKey key, CacheEntry entry, CancellationToken cancellationToken)
        {
            var tasks = new List <Task>();

            switch (this.dataConsistencyPolicy)
            {
            case CachingBotDataStoreConsistencyPolicy.LastWriteWins:
                if (entry?.BotConversationData != null)
                {
                    entry.BotConversationData.ETag = "*";
                }

                if (entry?.BotUserData != null)
                {
                    entry.BotUserData.ETag = "*";
                }

                if (entry?.BotPrivateConversationData != null)
                {
                    entry.BotPrivateConversationData.ETag = "*";
                }
                break;

            case CachingBotDataStoreConsistencyPolicy.ETagBasedConsistency:
                // no action needed, store relies on the ETags returned by inner store
                break;

            default:
                throw new ArgumentException($"{this.dataConsistencyPolicy} is not a valid consistency policy!");
            }

            if (entry?.BotConversationData != null)
            {
                tasks.Add(inner.SaveAsync(key, BotStoreType.BotConversationData, entry.BotConversationData, cancellationToken));
            }

            if (entry?.BotUserData != null)
            {
                tasks.Add(inner.SaveAsync(key, BotStoreType.BotUserData, entry.BotUserData, cancellationToken));
            }

            if (entry?.BotPrivateConversationData != null)
            {
                tasks.Add(inner.SaveAsync(key, BotStoreType.BotPrivateConversationData, entry.BotPrivateConversationData, cancellationToken));
            }
            await Task.WhenAll(tasks);
        }
Пример #13
0
        private string GetKey(BotDataKey key, BotStoreType botStoreType)
        {
            switch (botStoreType)
            {
            case BotStoreType.BotConversationData:
                return($"conversation:{key.BotId}:{key.ConversationId}");

            case BotStoreType.BotUserData:
                return($"user:{key.BotId}:{key.UserId}");

            case BotStoreType.BotPerUserInConversationData:
                return($"perUserInConversation:{key.BotId}:{key.UserId}:{key.ConversationId}");

            default:
                throw new ArgumentException("Unsupported bot store type!");
            }
        }
Пример #14
0
        private void Save(BotDataKey key, DataEntry entry)
        {
            if (entry?.BotConversationData != null)
            {
                store[GetKey(key, BotStoreType.BotConversationData)] = JsonConvert.SerializeObject(entry.BotConversationData);
            }

            if (entry?.BotUserData != null)
            {
                store[GetKey(key, BotStoreType.BotUserData)] = JsonConvert.SerializeObject(entry.BotUserData);
            }

            if (entry?.BotPerUserInConversationData != null)
            {
                store[GetKey(key, BotStoreType.BotPerUserInConversationData)] = JsonConvert.SerializeObject(entry.BotPerUserInConversationData);
            }
        }
Пример #15
0
        private async Task Save(BotDataKey key, DataEntry entry, CancellationToken cancellationToken)
        {
            if (entry?.BotConversationData != null)
            {
                await inner.SaveAsync(key, BotStoreType.BotConversationData, new BotData { ETag = "*", Data = entry.BotConversationData }, cancellationToken);
            }

            if (entry?.BotUserData != null)
            {
                await inner.SaveAsync(key, BotStoreType.BotUserData, new BotData { ETag = "*", Data = entry.BotUserData }, cancellationToken);
            }

            if (entry?.BotPrivateConversationData != null)
            {
                await inner.SaveAsync(key, BotStoreType.BotPrivateConversationData, new BotData { ETag = "*", Data = entry.BotPrivateConversationData }, cancellationToken);
            }
        }
Пример #16
0
        async Task <BotData> IBotDataStore <BotData> .LoadAsync(BotDataKey key, BotStoreType botStoreType, CancellationToken cancellationToken)
        {
            CacheEntry cacheEntry;
            BotData    value = null;

            if (!cache.TryGetValue(key, out cacheEntry))
            {
                cacheEntry = new CacheEntry();
                cache.Add(key, cacheEntry);
                value = await LoadFromInnerAndCache(cacheEntry, botStoreType, key, cancellationToken);
            }
            else
            {
                switch (botStoreType)
                {
                case BotStoreType.BotConversationData:
                    if (cacheEntry.BotConversationData != null)
                    {
                        value = cacheEntry.BotConversationData;
                    }
                    break;

                case BotStoreType.BotPrivateConversationData:
                    if (cacheEntry.BotPrivateConversationData != null)
                    {
                        value = cacheEntry.BotPrivateConversationData;
                    }
                    break;

                case BotStoreType.BotUserData:
                    if (cacheEntry.BotUserData != null)
                    {
                        value = cacheEntry.BotUserData;
                    }
                    break;
                }

                if (value == null)
                {
                    value = await LoadFromInnerAndCache(cacheEntry, botStoreType, key, cancellationToken);
                }
            }

            return(value);
        }
Пример #17
0
        async Task <bool> IBotDataStore <BotData> .FlushAsync(BotDataKey key, CancellationToken cancellationToken)
        {
            CacheEntry entry = default(CacheEntry);

            if (cache.TryGetValue(key, out entry))
            {
                // Removing the cached entry to make sure that we are not leaking
                // flushed entries when CachingBotDataStore is registered as a singleton object.
                // Also since this store is not updating ETags on LoadAsync(...), there
                // will be a conflict if we reuse the cached entries after flush.
                cache.Remove(key);
                await this.Save(key, entry, cancellationToken);

                return(true);
            }
            else
            {
                return(false);
            }
        }
Пример #18
0
        public Task <T> LoadAsync <T>(BotDataKey key, BotStoreType botStoreType)
        {
            try
            {
                if (!ValidateKey(key))
                {
                    throw new ArgumentException("Invalid bot data key!");
                }

                var value = default(T);

                switch (botStoreType.ToString())
                {
                case nameof(message.BotConversationData):
                    value = (T)message.BotConversationData;
                    break;

                case nameof(message.BotPerUserInConversationData):
                    value = (T)message.BotPerUserInConversationData;
                    break;

                case nameof(message.BotUserData):
                    value = (T)message.BotUserData;
                    break;

                default:
                    value = default(T);
                    break;
                }
                return(Task.FromResult(value));
            }
            catch (Exception e)
            {
                return(Task.FromException <T>(e));
            }
        }
Пример #19
0
 public BotDataBase(Message message, IBotDataStore botDataStore)
 {
     SetField.NotNull(out this.botDataStore, nameof(BotDataBase <T> .botDataStore), botDataStore);
     SetField.CheckNull(nameof(message), message);
     this.botDataKey = message.GetBotDataKey();
 }
Пример #20
0
        private async Task <BotData> LoadFromInnerAndCache(CacheEntry cacheEntry, BotStoreType botStoreType, BotDataKey key, CancellationToken token)
        {
            var value = await inner.LoadAsync(key, botStoreType, token);

            if (value != null)
            {
                SetCachedValue(cacheEntry, botStoreType, value);
            }
            else
            {
                // inner store returned null, we create a new instance of BotData with ETag = "*"
                value = new BotData()
                {
                    ETag = "*"
                };
                SetCachedValue(cacheEntry, botStoreType, value);
            }
            return(value);
        }
Пример #21
0
 Task <bool> IBotDataStore <BotData> .FlushAsync(BotDataKey key, CancellationToken cancellationToken)
 {
     // Everything is saved. Flush is no-op
     return(Task.FromResult(true));
 }
Пример #22
0
 public BotDataBase(IBotIdResolver botIdResolver, IMessageActivity message, IBotDataStore botDataStore)
 {
     SetField.NotNull(out this.botDataStore, nameof(BotDataBase <T> .botDataStore), botDataStore);
     SetField.CheckNull(nameof(message), message);
     this.botDataKey = message.GetBotDataKey(botIdResolver.BotId);
 }
Пример #23
0
 private bool ValidateKey(BotDataKey key)
 {
     return(key.UserId == message.From?.Id &&
            key.BotId == message.To?.Id &&
            key.ConversationId == message.ConversationId);
 }
Пример #24
0
 public Task <bool> FlushAsync(BotDataKey key)
 {
     // no-op for message backed store
     return(Task.FromResult(ValidateKey(key)));
 }