public static CompareExchangeValue <T> GetSingleValue(BlittableJsonReaderObject item, bool materializeMetadata, DocumentConventions conventions) { if (item == null) { return(null); } if (item.TryGet(nameof(CompareExchangeValue <T> .Key), out string key) == false) { throw new InvalidDataException("Response is invalid. Key is missing."); } if (item.TryGet(nameof(CompareExchangeValue <T> .Index), out long index) == false) { throw new InvalidDataException("Response is invalid. Index is missing."); } if (item.TryGet(nameof(CompareExchangeValue <T> .Value), out BlittableJsonReaderObject raw) == false) { throw new InvalidDataException("Response is invalid. Value is missing."); } var type = typeof(T); if (raw == null) { return(new CompareExchangeValue <T>(key, index, default)); } MetadataAsDictionary metadata = null; if (raw.TryGet(Constants.Documents.Metadata.Key, out BlittableJsonReaderObject bjro) && bjro != null) { metadata = materializeMetadata == false ? new MetadataAsDictionary(bjro) : MetadataAsDictionary.MaterializeFromBlittable(bjro); } if (type.IsPrimitive || type == typeof(string)) { // simple raw.TryGet(Constants.CompareExchange.ObjectFieldName, out T value); return(new CompareExchangeValue <T>(key, index, value, metadata)); } if (type == typeof(BlittableJsonReaderObject)) { if (raw.TryGetMember(Constants.CompareExchange.ObjectFieldName, out object rawValue) == false) { return(new CompareExchangeValue <T>(key, index, default, metadata));
public async Task StoreAsync(object entity, string id, IMetadataDictionary metadata = null) { if (Interlocked.CompareExchange(ref _concurrentCheck, 1, 0) == 1) { throw new InvalidOperationException("Bulk Insert store methods cannot be executed concurrently."); } try { VerifyValidId(id); if (_stream == null) { await WaitForId().ConfigureAwait(false); await EnsureStream().ConfigureAwait(false); } if (_bulkInsertExecuteTask.IsFaulted) { try { await _bulkInsertExecuteTask.ConfigureAwait(false); } catch (Exception e) { await ThrowBulkInsertAborted(e).ConfigureAwait(false); } } if (metadata == null) { metadata = new MetadataAsDictionary(); } if (metadata.ContainsKey(Constants.Documents.Metadata.Collection) == false) { var collection = _requestExecutor.Conventions.GetCollectionName(entity); if (collection != null) { metadata.Add(Constants.Documents.Metadata.Collection, collection); } } if (metadata.ContainsKey(Constants.Documents.Metadata.RavenClrType) == false) { var clrType = _requestExecutor.Conventions.GetClrTypeName(entity.GetType()); if (clrType != null) { metadata[Constants.Documents.Metadata.RavenClrType] = clrType; } } if (_first == false) { _currentWriter.Write(','); } _first = false; try { _currentWriter.Write("{\"Id\":\""); WriteId(_currentWriter, id); _currentWriter.Write("\",\"Type\":\"PUT\",\"Document\":"); if (_customEntitySerializer == null || _customEntitySerializer(entity, metadata, _currentWriter) == false) { using (var json = EntityToBlittable.ConvertEntityToBlittable(entity, _conventions, _context, _defaultSerializer, new DocumentInfo { MetadataInstance = metadata })) { _currentWriter.Flush(); json.WriteJsonTo(_currentWriter.BaseStream); } } _currentWriter.Write("}"); _currentWriter.Flush(); if (_currentWriter.BaseStream.Position > _maxSizeInBuffer || _asyncWrite.IsCompleted) { await _asyncWrite.ConfigureAwait(false); var tmp = _currentWriter; _currentWriter = _backgroundWriter; _backgroundWriter = tmp; _currentWriter.BaseStream.SetLength(0); ((MemoryStream)tmp.BaseStream).TryGetBuffer(out var buffer); _asyncWrite = _requestBodyStream.WriteAsync(buffer.Array, buffer.Offset, buffer.Count, _token); } } catch (Exception e) { var error = await GetExceptionFromOperation().ConfigureAwait(false); if (error != null) { throw error; } await ThrowOnUnavailableStream(id, e).ConfigureAwait(false); } } finally { Interlocked.CompareExchange(ref _concurrentCheck, 0, 1); } void WriteId(StreamWriter writer, string input) { for (var i = 0; i < input.Length; i++) { var c = input[i]; if (c == '"') { if (i == 0 || input[i - 1] != '\\') { writer.Write("\\"); } } writer.Write(c); } } }
public async Task CanAddManyCompareExchangeWithExpirationAndEditExpiration(int count) { using var server = GetNewServer(); using (var store = GetDocumentStore(new Options { Server = server })) { var expiry = DateTime.Now.AddMinutes(2); var compareExchanges = new Dictionary <string, User>(); var compareExchangeIndexes = new Dictionary <string, long>(); for (int i = 0; i < count; i++) { var rnd = new Random(DateTime.Now.Millisecond); var user = new User { Name = new string(Enumerable.Repeat(_chars, 10).Select(s => s[rnd.Next(s.Length)]).ToArray()) }; var key = $"{new string(Enumerable.Repeat(_chars, 10).Select(s => s[rnd.Next(s.Length)]).ToArray())}{i}"; compareExchanges[key] = user; using (var session = store.OpenAsyncSession(new SessionOptions { TransactionMode = TransactionMode.ClusterWide })) { var result = session.Advanced.ClusterTransaction.CreateCompareExchangeValue(key, user); result.Metadata[Constants.Documents.Metadata.Expires] = expiry; await session.SaveChangesAsync(); compareExchangeIndexes[key] = result.Index; } } await AssertCompareExchanges(compareExchanges, store, expiry); expiry = DateTime.Now.AddMinutes(4); foreach (var kvp in compareExchanges) { var metadata = new MetadataAsDictionary { [Constants.Documents.Metadata.Expires] = expiry }; await store.Operations.SendAsync(new PutCompareExchangeValueOperation <User>(kvp.Key, kvp.Value, compareExchangeIndexes[kvp.Key], metadata)); } await AssertCompareExchanges(compareExchanges, store, expiry); server.ServerStore.Observer.Time.UtcDateTime = () => DateTime.UtcNow.AddMinutes(3); Thread.Sleep(count == 10 ? 1000 : 3000); var stats = await store.Maintenance.SendAsync(new GetDetailedStatisticsOperation()); Assert.Equal(count, stats.CountOfCompareExchange); server.ServerStore.Observer.Time.UtcDateTime = () => DateTime.UtcNow.AddMinutes(5); var val = await WaitForValueAsync(async() => { var stats = await store.Maintenance.SendAsync(new GetDetailedStatisticsOperation()); return(stats.CountOfCompareExchange); }, 0); Assert.Equal(0, val); } }
public async Task StoreAsync(object entity, string id, IMetadataDictionary metadata = null) { VerifyValidId(id); if (_stream == null) { await WaitForId().ConfigureAwait(false); await EnsureStream().ConfigureAwait(false); } if (metadata == null) { metadata = new MetadataAsDictionary(); } if (metadata.ContainsKey(Constants.Documents.Metadata.Collection) == false) { var collection = _requestExecutor.Conventions.GetCollectionName(entity); metadata.Add(Constants.Documents.Metadata.Collection, collection); } if (_first == false) { _currentWriter.Write(','); } _first = false; try { _currentWriter.Write("{'Id':'"); _currentWriter.Write(id); _currentWriter.Write("','Type':'PUT','Document':"); if (_customEntitySerializer == null || _customEntitySerializer(entity, _currentWriter) == false) { _defaultSerializer.Serialize(_currentWriter, entity); } _currentWriter.Flush(); _currentWriter.BaseStream.Position--; _currentWriter.Write(",'@metadata':"); if (_customMetadataSerializer == null || _customMetadataSerializer(entity, _currentWriter) == false) { _defaultSerializer.Serialize(_currentWriter, metadata); } _currentWriter.Write("}}"); _currentWriter.Flush(); if (_currentWriter.BaseStream.Position > _maxSizeInBuffer || _asyncWrite.IsCompleted) { await _asyncWrite.ConfigureAwait(false); var tmp = _currentWriter; _currentWriter = _backgroundWriter; _backgroundWriter = tmp; _currentWriter.BaseStream.SetLength(0); ((MemoryStream)tmp.BaseStream).TryGetBuffer(out var buffer); _asyncWrite = _requestBodyStream.WriteAsync(buffer.Array, buffer.Offset, buffer.Count, _token); } } catch (Exception e) { var error = await GetExceptionFromOperation().ConfigureAwait(false); if (error != null) { throw error; } await ThrowOnUnavailableStream(id, e).ConfigureAwait(false); } }
public async Task AsyncExample() { using (var documentStore = new DocumentStore()) { #region metadata_1 // Create some metadata var cmpxchgMetadata = new MetadataAsDictionary { ["Year"] = "2020" }; // Create/update the compare exchange value "best" await documentStore.Operations.SendAsync( new PutCompareExchangeValueOperation <User>( "best", new User { Name = "Alice" }, 0, cmpxchgMetadata)); #endregion // -Include examples- #region include_load using (IDocumentSession session = documentStore.OpenSession()) { // Load a user document, include the compare exchange value // with the key equal to the user's Name field var user = session.Load <User>("users/1-A", includes => includes.IncludeCompareExchangeValue( x => x.Name)); // Getting the compare exchange value does not require // another call to the server var value = session.Advanced.ClusterTransaction .GetCompareExchangeValue <string>(user.Name); } #endregion #region include_load_async using (IAsyncDocumentSession session = documentStore.OpenAsyncSession()) { // Load a user document, include the compare exchange value // with the key equal to the user's Name field var user = await session.LoadAsync <User>("users/1-A", includes => includes.IncludeCompareExchangeValue( x => x.Name)); // Getting the compare exchange value does not require // another call to the server var value = await session.Advanced.ClusterTransaction .GetCompareExchangeValueAsync <string>(user.Name); } #endregion using (IDocumentSession session = documentStore.OpenSession()) { #region include_linq_query var users = session.Query <User>() .Include(builder => builder.IncludeCompareExchangeValue(x => x.Name)) .ToList(); List <CompareExchangeValue <string> > compareExchangeValues = null; // Getting the compare exchange values does not require // additional calls to the server foreach (User u in users) { compareExchangeValues.Add(session.Advanced.ClusterTransaction .GetCompareExchangeValue <string>(u.Name)); } #endregion } using (IDocumentSession session = documentStore.OpenSession()) { #region include_raw_query // First method: from body of query var users1 = session.Advanced .RawQuery <User>(@" from Users as u select u include cmpxchg(u.Name)" ) .ToList(); List <CompareExchangeValue <string> > compareExchangeValues1 = null; // Getting the compare exchange values does not require // additional calls to the server foreach (User u in users1) { compareExchangeValues1.Add(session.Advanced.ClusterTransaction .GetCompareExchangeValue <string>(u.Name)); } // Second method: from a JavaScript function var users2 = session.Advanced .RawQuery <User>(@" declare function includeCEV(user) { includes.cmpxchg(user.Name); return user; } from Users as u select includeCEV(u)" ) .ToList(); // Note that includeCEV() returns the same User // entity it received, without modifying it List <CompareExchangeValue <string> > compareExchangeValues2 = null; // Does not require calls to the server foreach (User u in users2) { compareExchangeValues2.Add(session.Advanced.ClusterTransaction .GetCompareExchangeValue <string>(u.Name)); } #endregion } } }
public async Task StoreAsync(object entity, string id, IMetadataDictionary metadata = null) { using (ConcurrencyCheck()) { VerifyValidId(id); await ExecuteBeforeStore().ConfigureAwait(false); if (metadata == null) { metadata = new MetadataAsDictionary(); } if (metadata.ContainsKey(Constants.Documents.Metadata.Collection) == false) { var collection = _requestExecutor.Conventions.GetCollectionName(entity); if (collection != null) { metadata.Add(Constants.Documents.Metadata.Collection, collection); } } if (metadata.ContainsKey(Constants.Documents.Metadata.RavenClrType) == false) { var clrType = _requestExecutor.Conventions.GetClrTypeName(entity); if (clrType != null) { metadata[Constants.Documents.Metadata.RavenClrType] = clrType; } } EndPreviousCommandIfNeeded(); try { if (_first == false) { WriteComma(); } _first = false; _inProgressCommand = CommandType.None; _currentWriter.Write("{\"Id\":\""); WriteString(id); _currentWriter.Write("\",\"Type\":\"PUT\",\"Document\":"); await FlushIfNeeded().ConfigureAwait(false); if (_customEntitySerializer == null || _customEntitySerializer(entity, metadata, _currentWriter) == false) { using (var json = _conventions.Serialization.DefaultConverter.ToBlittable(entity, metadata, _context, _defaultSerializer)) json.WriteJsonTo(_currentWriter.BaseStream); } _currentWriter.Write('}'); } catch (Exception e) { await HandleErrors(id, e).ConfigureAwait(false); } } }