public async Task ReadStateAsync(string grainType, GrainReference grainReference, IGrainState grainState) { EnsureNotClosed(); var meta = grainState.ToGrainMeta(grainReference, grainType, _serviceId); try { var collectionName = Naming.CollectionNameForGrain(grainType, _options.CollectionNamePrefix); var collection = _database.GetCollection <MongoGrain>(collectionName); var id = Naming.PrimaryKeyForGrain(_serviceId, grainReference); LogVerbose3($"Reading data: {meta}", MongoStorageLogCode.TraceReading); var doc = await collection.Find(x => x.Id == id).FirstOrDefaultAsync(); if (doc == null) { LogVerbose3($"Grain state not found. {meta}", MongoStorageLogCode.TraceNotFound); return; } grainState.ETag = doc.Meta.ETag; grainState.State = doc.Data; LogVerbose3($"Read data: {meta}", MongoStorageLogCode.TraceRead); } catch (Exception ex) { LogError($"Error while reading. {meta} Error={ex.Message}", MongoStorageLogCode.ErrorRead, ex); throw; } }
public static MongoGrain ToGrain(this IGrainState grainState, GrainReference reference, string grainType, Guid serviceId) { return(new MongoGrain { Id = Naming.PrimaryKeyForGrain(serviceId, reference), Data = grainState.State, Meta = grainState.ToGrainMeta(reference, grainType, serviceId) }); }
public async Task WriteStateAsync(string grainType, GrainReference grainReference, IGrainState grainState) { EnsureNotClosed(); var meta = grainState.ToGrainMeta(grainReference, grainType, _serviceId); try { var collectionName = Naming.CollectionNameForGrain(grainType, _options.CollectionNamePrefix); var collection = _database.GetCollection <MongoGrain>(collectionName); LogVerbose3($"Writing data: {meta}", MongoStorageLogCode.TraceWriting); if (string.IsNullOrEmpty(grainState.ETag)) { var grain = grainState.ToGrain(grainReference, grainType, _serviceId); grain.Meta.Timestamp = DateTime.UtcNow.Ticks; await collection.InsertOneAsync(grain); grainState.ETag = grain.Meta.ETag; } else { var id = Naming.PrimaryKeyForGrain(_serviceId, grainReference); // Update data and generate new timestamp var update = Builders <MongoGrain> .Update .Set(x => x.Data, grainState.State) .Set(x => x.Meta.Timestamp, DateTime.UtcNow.Ticks); var options = new FindOneAndUpdateOptions <MongoGrain> { IsUpsert = false, ReturnDocument = ReturnDocument.After, Projection = Builders <MongoGrain> .Projection.Include(x => x.Meta) }; var updatedGrain = await collection.FindOneAndUpdateAsync <MongoGrain>( x => x.Id == id && x.Meta.Timestamp == meta.Timestamp, update, options); if (updatedGrain == null) { var message = $"Inconsistent state for grain: {meta}. ETag has changed or document has already been deleted."; throw new InconsistentStateException(message); } grainState.ETag = updatedGrain.Meta.ETag; } LogVerbose3($"Wrote data: {meta}", MongoStorageLogCode.TraceWrite); } catch (Exception ex) { LogError($"Error while writing. {meta} Error={ex.Message}", MongoStorageLogCode.ErrorWrite, ex); throw; } }
public async Task ClearStateAsync(string grainType, GrainReference grainReference, IGrainState grainState) { EnsureNotClosed(); var meta = grainState.ToGrainMeta(grainReference, grainType, _serviceId); try { var collectionName = Naming.CollectionNameForGrain(grainType, _options.CollectionNamePrefix); var collection = _database.GetCollection <MongoGrain>(collectionName); LogVerbose3($"Deleting data: {meta}", MongoStorageLogCode.TraceDeleting); var id = Naming.PrimaryKeyForGrain(_serviceId, grainReference); await collection.DeleteOneAsync(x => x.Id == id); grainState.ETag = null; LogVerbose3($"Deleted data: {meta}", MongoStorageLogCode.TraceDelete); } catch (Exception ex) { LogError($"Error while deleting. {meta} Error={ex.Message}", MongoStorageLogCode.ErrorDelete, ex); throw; } }