Пример #1
0
        public static async Task <Uri> AddToCatalog(CatalogItem catalogItem, string connectionString, string container, string catalogBaseAddress)
        {
            StorageWriteLock writeLock = new StorageWriteLock(connectionString, container);

            await writeLock.AquireAsync();

            Uri rootUri = null;

            Exception exception = null;

            try
            {
                Storage storage = CreateStorage(connectionString, container, catalogBaseAddress);

                AppendOnlyCatalogWriter writer = new AppendOnlyCatalogWriter(storage);
                writer.Add(catalogItem);
                await writer.Commit();

                rootUri = writer.RootUri;
            }
            catch (Exception e)
            {
                exception = e;
            }

            await writeLock.ReleaseAsync();

            if (exception != null)
            {
                throw exception;
            }

            return(rootUri);
        }
Пример #2
0
        public async Task LockFailTest()
        {
            var etagOriginal = this.rand.NextString();

            var model = new ValueModel
            {
                Value = this.rand.NextString()
            };

            model.Locked = true;
            var dataOriginal = JsonConvert.SerializeObject(model);

            var @lock = new StorageWriteLock <ValueModel>(
                this.mockClient.Object,
                COLL,
                KEY,
                (v, b) => v.Locked = b,
                m => !JsonConvert.DeserializeObject <ValueModel>(m.Data).Locked);

            this.mockClient
            .Setup(x => x.GetAsync(
                       It.Is <string>(s => s == COLL),
                       It.Is <string>(s => s == KEY)))
            .ReturnsAsync(new ValueApiModel
            {
                Data = dataOriginal,
                ETag = etagOriginal
            });

            var result = await @lock.TryLockAsync();

            Assert.False(result.Value);
        }
Пример #3
0
        public async Task <bool> TryRebuildCacheAsync(bool force = false)
        {
            var @lock = new StorageWriteLock <CacheValue>(
                this.storageClient,
                CACHE_COLLECTION_ID,
                CACHE_KEY,
                (c, b) => c.Rebuilding = b,
                m => this.NeedBuild(force, m));

            while (true)
            {
                var locked = await @lock.TryLockAsync();

                if (locked == null)
                {
                    this.log.Warn("Cache rebuilding: lock failed due to conflict. Retry soon", () => { });
                    continue;
                }

                if (!locked.Value)
                {
                    return(false);
                }

                // Build the cache content
                var twinNamesTask       = this.GetValidNamesAsync();
                var simulationNamesTask = this.simulationClient.GetDevicePropertyNamesAsync();

                try
                {
                    Task.WaitAll(twinNamesTask, simulationNamesTask);
                }
                catch (Exception)
                {
                    this.log.Warn($"Some underlying service is not ready. Retry after {this.serviceQueryInterval}", () => { });
                    await @lock.ReleaseAsync();

                    await Task.Delay(this.serviceQueryInterval);

                    continue;
                }

                var twinNames = twinNamesTask.Result;
                twinNames.ReportedProperties.UnionWith(simulationNamesTask.Result);

                var updated = await @lock.WriteAndReleaseAsync(new CacheValue
                {
                    Tags     = twinNames.Tags,
                    Reported = twinNames.ReportedProperties
                });

                if (updated)
                {
                    return(true);
                }

                this.log.Warn("Cache rebuilding: write failed due to conflict. Retry soon", () => { });
            }
        }
Пример #4
0
        public async Task ReleaseAndWriteAsyncWithoutLockTest()
        {
            var @lock = new StorageWriteLock <ValueModel>(
                this.mockClient.Object,
                COLL,
                KEY,
                (v, b) => v.Locked = b,
                m => true);

            await Assert.ThrowsAsync <ResourceOutOfDateException>(() => @lock.WriteAndReleaseAsync(null));
        }
Пример #5
0
        public async Task LockConflictTest()
        {
            var etagOriginal = this.rand.NextString();

            var model = new ValueModel
            {
                Value = this.rand.NextString()
            };

            model.Locked = false;
            var dataOriginal = JsonConvert.SerializeObject(model);

            model.Locked = true;
            var dataLocked = JsonConvert.SerializeObject(model);

            var @lock = new StorageWriteLock <ValueModel>(
                this.mockClient.Object,
                COLL,
                KEY,
                (v, b) => v.Locked = b,
                m => !JsonConvert.DeserializeObject <ValueModel>(m.Data).Locked);

            this.mockClient
            .Setup(x => x.GetAsync(
                       It.Is <string>(s => s == COLL),
                       It.Is <string>(s => s == KEY)))
            .ReturnsAsync(new ValueApiModel
            {
                Data = dataOriginal,
                ETag = etagOriginal
            });

            this.mockClient
            .Setup(x => x.UpdateAsync(
                       It.Is <string>(s => s == COLL),
                       It.Is <string>(s => s == KEY),
                       It.Is <string>(s => s == dataLocked),
                       It.Is <string>(s => s == etagOriginal)))
            .ThrowsAsync(new ConflictingResourceException());

            var result = await @lock.TryLockAsync();

            Assert.Null(result);
        }
Пример #6
0
        /// <summary>
        /// Try to create cache of deviceProperties if lock failed retry after 10 seconds
        /// </summary>
        public async Task <bool> TryRecreateListAsync(bool force = false)
        {
            var @lock = new StorageWriteLock <DevicePropertyServiceModel>(
                this.storageClient,
                CACHE_COLLECTION_ID,
                CACHE_KEY,
                (c, b) => c.Rebuilding = b,
                m => this.ShouldCacheRebuild(force, m));

            while (true)
            {
                var locked = await @lock.TryLockAsync();

                if (locked == null)
                {
                    this.log.Warn("Cache rebuilding: lock failed due to conflict. Retry soon", () => { });
                    continue;
                }

                if (!locked.Value)
                {
                    return(false);
                }

                // Build the cache content
                var twinNamesTask = this.GetValidNamesAsync();

                try
                {
                    Task.WaitAll(twinNamesTask);
                }
                catch (Exception)
                {
                    this.log.Warn(
                        $"Some underlying service is not ready. Retry after {this.serviceQueryInterval}",
                        () => { });
                    try
                    {
                        await @lock.ReleaseAsync();
                    }
                    catch (Exception e)
                    {
                        log.Error("Cache rebuilding: Unable to release lock", () => e);
                    }
                    await Task.Delay(this.serviceQueryInterval);

                    continue;
                }

                var twinNames = twinNamesTask.Result;
                try
                {
                    var updated = await @lock.WriteAndReleaseAsync(
                        new DevicePropertyServiceModel
                    {
                        Tags     = twinNames.Tags,
                        Reported = twinNames.ReportedProperties
                    });

                    if (updated)
                    {
                        this.DevicePropertiesLastUpdated = DateTime.Now;
                        return(true);
                    }
                }
                catch (Exception e)
                {
                    log.Error("Cache rebuilding: Unable to write and release lock", () => e);
                }
                this.log.Warn("Cache rebuilding: write failed due to conflict. Retry soon", () => { });
            }
        }
Пример #7
0
        /// <summary>
        /// Try to create cache of deviceProperties if lock failed retry after 10 seconds
        /// </summary>
        public async Task <bool> TryRecreateListAsync(bool force = false)
        {
            var @lock = new StorageWriteLock <DevicePropertyServiceModel>(
                this.storageClient,
                CACHE_COLLECTION_ID,
                CACHE_KEY,
                (c, b) => c.Rebuilding = b,
                m => this.ShouldCacheRebuild(force, m));

            while (true)
            {
                //var locked = await @lock.TryLockAsync();
                //if (locked == null)
                //{
                //    this.log.Warn("Cache rebuilding: lock failed due to conflict. Retry soon", () => { });
                //    continue;
                //}

                //if (!locked.Value)
                //{
                //    return false;
                //}

                // Build the cache content
                var twinNamesTask = this.GetValidNamesAsync();

                try
                {
                    Task.WaitAll(twinNamesTask);
                }
                catch (Exception)
                {
                    this.log.Warn(
                        $"Some underlying service is not ready. Retry after {this.serviceQueryInterval}",
                        () => { });
                    try
                    {
                        //await @lock.ReleaseAsync();
                    }
                    catch (Exception e)
                    {
                        log.Error("Cache rebuilding: Unable to release lock", () => e);
                    }
                    await Task.Delay(this.serviceQueryInterval);

                    continue;
                }

                var twinNames = twinNamesTask.Result;
                try
                {
                    var model = await this.storageClient.GetAllAsync(CACHE_COLLECTION_ID);

                    foreach (var item in model.Items)
                    {
                        await this.storageClient.DeleteAsync(CACHE_COLLECTION_ID, item.objectid);
                    }
                    DevicePropertyServiceModel devicepropertites = new DevicePropertyServiceModel();
                    devicepropertites.Tags     = twinNames.Tags;
                    devicepropertites.Reported = twinNames.ReportedProperties;
                    var value = JsonConvert.SerializeObject(devicepropertites, Formatting.Indented, new JsonSerializerSettings {
                        NullValueHandling = NullValueHandling.Ignore
                    });
                    var Createdevicepropertites = await this.storageClient.CreateAsync(CACHE_COLLECTION_ID, value);

                    //var updated = await @lock.WriteAndReleaseAsync(
                    //    new DevicePropertyServiceModel
                    //    {
                    //        Tags = twinNames.Tags,
                    //        Reported = twinNames.ReportedProperties
                    //    });

                    if (Createdevicepropertites.objectid != null)
                    {
                        this.DevicePropertiesLastUpdated = DateTime.Now;
                        return(true);
                    }
                }
                catch (Exception e)
                {
                    log.Error("Cache rebuilding: Unable to write and release lock", () => e);
                }
                this.log.Warn("Cache rebuilding: write failed due to conflict. Retry soon", () => { });
            }
        }
Пример #8
0
        public async Task NormalLoopTest()
        {
            var etagOriginal = this.rand.NextString();
            var etagLocked   = this.rand.NextString();
            var etagUpdated  = this.rand.NextString();

            var model = new ValueModel
            {
                Value = this.rand.NextString()
            };

            model.Locked = false;
            var dataOriginal = JsonConvert.SerializeObject(model);

            model.Locked = true;
            var dataLocked = JsonConvert.SerializeObject(model);

            model.Value  = this.rand.NextString();
            model.Locked = false;
            var dataUpdated = JsonConvert.SerializeObject(model);

            var @lock = new StorageWriteLock <ValueModel>(
                this.mockClient.Object,
                COLL,
                KEY,
                (v, b) => v.Locked = b,
                m => !JsonConvert.DeserializeObject <ValueModel>(m.Data).Locked);

            this.mockClient
            .Setup(x => x.GetAsync(
                       It.Is <string>(s => s == COLL),
                       It.Is <string>(s => s == KEY)))
            .ReturnsAsync(new ValueApiModel
            {
                Data = dataOriginal,
                ETag = etagOriginal
            });

            this.mockClient
            .Setup(x => x.UpdateAsync(
                       It.Is <string>(s => s == COLL),
                       It.Is <string>(s => s == KEY),
                       It.Is <string>(s => s == dataLocked),
                       It.Is <string>(s => s == etagOriginal)))
            .ReturnsAsync(new ValueApiModel
            {
                ETag = etagLocked
            });

            var lockResult = await @lock.TryLockAsync();

            Assert.True(lockResult.Value);

            this.mockClient
            .Verify(x => x.GetAsync(
                        It.Is <string>(s => s == COLL),
                        It.Is <string>(s => s == KEY)),
                    Times.Once);

            this.mockClient
            .Verify(x => x.GetAsync(
                        It.Is <string>(s => s == COLL),
                        It.Is <string>(s => s == KEY)),
                    Times.Once);

            this.mockClient
            .Verify(x => x.UpdateAsync(
                        It.Is <string>(s => s == COLL),
                        It.Is <string>(s => s == KEY),
                        It.Is <string>(s => s == dataLocked),
                        It.Is <string>(s => s == etagOriginal)),
                    Times.Once);

            this.mockClient
            .Setup(x => x.UpdateAsync(
                       It.Is <string>(s => s == COLL),
                       It.Is <string>(s => s == KEY),
                       It.Is <string>(s => s == dataUpdated),
                       It.Is <string>(s => s == etagLocked)))
            .ReturnsAsync(new ValueApiModel
            {
                ETag = etagUpdated
            });

            var writeResult = await @lock.WriteAndReleaseAsync(model);

            Assert.True(writeResult);

            this.mockClient
            .Verify(x => x.UpdateAsync(
                        It.Is <string>(s => s == COLL),
                        It.Is <string>(s => s == KEY),
                        It.Is <string>(s => s == dataUpdated),
                        It.Is <string>(s => s == etagLocked)),
                    Times.Once);
        }