private DateTimeOffset GetVersion(ConcurrentMetadataText item)
        {
            if (item == null)
            {
                return(DateTimeOffset.MinValue);
            }

            return(GetVersion(item.Metadata));
        }
        public VersionedMetadataText Read(string id)
        {
            ConcurrentMetadataText innerItem = _innerStore.Read(id);

            if (innerItem == null)
            {
                return(null);
            }

            DateTimeOffset version = GetVersion(innerItem.Metadata);

            return(new VersionedMetadataText(innerItem.ETag, innerItem.Metadata, version, innerItem.Text));
        }
        public ConcurrentMetadataDocument <TDocument> Read(string id)
        {
            ConcurrentMetadataText innerResult = _innerStore.Read(id);

            if (innerResult == null)
            {
                return(null);
            }

            string eTag = innerResult.ETag;
            IDictionary <string, string> metadata = innerResult.Metadata;
            TDocument document = JsonConvert.DeserializeObject <TDocument>(innerResult.Text, SerializerSettings);

            return(new ConcurrentMetadataDocument <TDocument>(eTag, metadata, document));
        }
 private static IConcurrentMetadataTextStore CreateInnerStore(string id, ConcurrentMetadataText item)
 {
     return CreateInnerStore(new Dictionary<string, ConcurrentMetadataText> { { id, item } });
 }
        private static void AssertEqual(ConcurrentMetadataText expected, ConcurrentMetadataText actual)
        {
            if (expected == null)
            {
                Assert.Null(actual);
                return;
            }

            Assert.NotNull(actual);
            Assert.Equal(expected.ETag, actual.ETag);
            Assert.Equal(expected.Metadata, actual.Metadata);
            Assert.Equal(expected.Text, actual.Text);
        }
        public void DeleteIfLatestWithoutCurrentData_DoesNotDelete_IfNewerExists()
        {
            // Arrange
            IVersionMetadataMapper versionMapper = CreateMapper();
            string id = "Id";

            ConcurrentMetadataText existingItem = new ConcurrentMetadataText("1",
                CreateMetadata(DateTimeOffset.MaxValue, versionMapper, "ExistingKey", "ExistingValue"), "ExistingText");
            IConcurrentMetadataTextStore innerStore = CreateInnerStore(id, existingItem);

            IVersionedMetadataTextStore product = CreateProductUnderTest(innerStore, versionMapper);

            // Act
            bool isLatest = product.DeleteIfLatest(id, DateTimeOffset.Now);

            // Assert
            Assert.False(isLatest);
            ConcurrentMetadataText storedItem = innerStore.Read(id);
            Assert.Same(existingItem, storedItem);
        }
        public void DeleteIfLatestWithCurrentData_Deletes_IfOlderExists()
        {
            // Arrange
            IVersionMetadataMapper versionMapper = CreateMapper();
            string id = "Id";

            DateTimeOffset existingVersion = DateTimeOffset.Now;
            ConcurrentMetadataText existingItem = new ConcurrentMetadataText("1",
                CreateMetadata(existingVersion, versionMapper, "ExistingKey", "ExistingValue"), "ExistingText");
            IConcurrentMetadataTextStore innerStore = CreateInnerStore(id, existingItem);

            IVersionedMetadataTextStore product = CreateProductUnderTest(innerStore, versionMapper);

            // Act
            bool isLatest = product.DeleteIfLatest(id, DateTimeOffset.MaxValue, existingItem.ETag, existingVersion);

            // Assert
            Assert.True(isLatest);
            ConcurrentMetadataText storedItem = innerStore.Read(id);
            Assert.Null(storedItem);
        }
        public void UpdateOrCreateIfLatestWithoutCurrentData_Updates_IfOlderExists()
        {
            // Arrange
            IVersionMetadataMapper versionMapper = CreateMapper();
            string id = "Id";

            IConcurrentMetadataTextStore innerStore = CreateInnerStore(id, new ConcurrentMetadataText("1",
                CreateMetadata(DateTimeOffset.Now, versionMapper, "ExistingKey", "ExistingValue"),
                "ExistingText"));

            IVersionedMetadataTextStore product = CreateProductUnderTest(innerStore, versionMapper);

            DateTimeOffset newVersion = DateTimeOffset.MaxValue;
            IDictionary<string, string> newOtherMetadata = CreateMetadata("NewKey", "NewValue");
            string newText = "NewText";

            // Act
            bool isLatest = product.UpdateOrCreateIfLatest(id, newVersion, newOtherMetadata, newText);

            // Assert
            Assert.True(isLatest);
            ConcurrentMetadataText storedItem = innerStore.Read(id);
            IDictionary<string, string> expectedMetadata = CreateMetadata(newVersion, versionMapper, newOtherMetadata);
            ConcurrentMetadataText expectedItem = new ConcurrentMetadataText("2", expectedMetadata, newText);
            AssertEqual(expectedItem, storedItem);
        }
        public void UpdateOrCreateIfLatestWithCurrentData_DoesNotUpdate_IfNewerExists()
        {
            // Arrange
            IVersionMetadataMapper versionMapper = CreateMapper();
            string id = "Id";

            DateTimeOffset existingVersion = DateTimeOffset.MaxValue;
            ConcurrentMetadataText existingItem = new ConcurrentMetadataText("1",
                CreateMetadata(existingVersion, versionMapper, "ExistingKey", "ExistingValue"), "ExistingText");
            IConcurrentMetadataTextStore innerStore = CreateInnerStore(id, existingItem);

            IVersionedMetadataTextStore product = CreateProductUnderTest(innerStore, versionMapper);

            DateTimeOffset newVersion = DateTimeOffset.Now;
            IDictionary<string, string> newOtherMetadata = CreateMetadata("NewKey", "NewValue");
            string newText = "NewText";

            // Act
            bool isLatest = product.UpdateOrCreateIfLatest(id, newVersion, newOtherMetadata, newText, existingItem.ETag,
                existingVersion);

            // Assert
            Assert.False(isLatest);
            ConcurrentMetadataText storedItem = innerStore.Read(id);
            Assert.Same(existingItem, storedItem);
        }
        public void CreateOrUpdateIfLatest_Updates_IfOlderConcurrentlyExists()
        {
            // Arrange
            IVersionMetadataMapper versionMapper = CreateMapper();
            string id = "Id";

            ConcurrentInnerStore innerStore = new ConcurrentInnerStore(id, new ConcurrentMetadataText("1",
                CreateMetadata(DateTimeOffset.Now, versionMapper, "ExistingKey", "ExistingValue"),
                "ExistingText"));

            IDictionary<string, string> updatedMetadata = CreateMetadata(DateTimeOffset.Now, versionMapper,
                "UpdatedKey", "UpdatedValue");
            string updatedText = "UpdatedText";

            innerStore.OnReadMetadata += (calls) =>
            {
                if (calls == 0)
                {
                    Assert.True(innerStore.TryUpdate(id, "1", updatedMetadata, updatedText));
                }
            };

            IVersionedMetadataTextStore product = CreateProductUnderTest(innerStore, versionMapper);

            DateTimeOffset newVersion = DateTimeOffset.MaxValue;
            IDictionary<string, string> newOtherMetadata = CreateMetadata("NewKey", "NewValue");
            string newText = "NewText";

            // Act
            bool isLatest = product.CreateOrUpdateIfLatest(id, newVersion, newOtherMetadata, newText);

            // Assert
            Assert.True(isLatest);
            ConcurrentMetadataText storedItem = innerStore.Read(id);
            IDictionary<string, string> expectedMetadata = CreateMetadata(newVersion, versionMapper, newOtherMetadata);
            ConcurrentMetadataText expectedItem = new ConcurrentMetadataText("3", expectedMetadata, newText);
            AssertEqual(expectedItem, storedItem);
        }
        public void CreateOrUpdateIfLatest_DoesNotUpdate_IfSameVersionExists()
        {
            // Arrange
            IVersionMetadataMapper versionMapper = CreateMapper();
            string id = "Id";

            DateTimeOffset existingVersion = DateTimeOffset.MaxValue;
            IDictionary<string, string> existingOtherMetadata = CreateMetadata("ExistingKey", "ExistingValue");
            IDictionary<string, string> existingCombinedMetadata = CreateMetadata(existingVersion, versionMapper,
                existingOtherMetadata);
            string existingText = "ExstingText";
            ConcurrentMetadataText existingItem = new ConcurrentMetadataText("1", existingCombinedMetadata,
                existingText);
            IConcurrentMetadataTextStore innerStore = CreateInnerStore(id, existingItem);

            IVersionedMetadataTextStore product = CreateProductUnderTest(innerStore, versionMapper);

            // Act
            bool isLatest = product.CreateOrUpdateIfLatest(id, existingVersion, existingOtherMetadata, existingText);

            // Assert
            Assert.True(isLatest);
            ConcurrentMetadataText storedItem = innerStore.Read(id);
            Assert.Same(existingItem, storedItem);
        }
        public void CreateOrUpdateIfLatest_Creates_IfNotYetCreatedAndOtherMetadataIsNull()
        {
            // Arrange
            IConcurrentMetadataTextStore innerStore = CreateInnerStore();
            IVersionMetadataMapper versionMapper = CreateMapper();

            IVersionedMetadataTextStore product = CreateProductUnderTest(innerStore, versionMapper);

            string id = "Id";
            DateTimeOffset newVersion = DateTimeOffset.Now;
            IDictionary<string, string> newOtherMetadata = null;
            string newText = "Text";

            // Act
            bool isLatest = product.CreateOrUpdateIfLatest(id, newVersion, newOtherMetadata, newText);

            // Assert
            Assert.True(isLatest);
            ConcurrentMetadataText storedItem = innerStore.Read(id);
            Assert.NotNull(storedItem);
            IDictionary<string, string> expectedMetadata = CreateMetadata(newVersion, versionMapper);
            ConcurrentMetadataText expectedItem = new ConcurrentMetadataText("1", expectedMetadata, newText);
            AssertEqual(expectedItem, storedItem);
        }
            public bool TryUpdate(string id, string eTag, IDictionary<string, string> metadata, string text)
            {
                if (!_values.ContainsKey(id))
                {
                    return false;
                }

                ConcurrentMetadataText value = _values[id];

                if (value.ETag != eTag)
                {
                    return false;
                }

                _values[id] = new ConcurrentMetadataText((int.Parse(eTag) + 1).ToString(), metadata, text);
                return true;
            }
 public ConcurrentInnerStore(string id, ConcurrentMetadataText item)
     : this(new Dictionary<string, ConcurrentMetadataText> { { id, item } })
 {
 }