public async Task ReadStateAsync(string grainType, GrainReference grainReference, IGrainState grainState) { var tableResult = await _table.ExecuteAsync(TableOperation.Retrieve<DynamicTableEntity>(grainReference.ToKeyString(), grainType)); if (tableResult.Result == null) { return; } var entity = tableResult.Result as DynamicTableEntity; var serializer = new JsonSerializer(); using (var memoryStream = new MemoryStream()) { foreach (var propertyName in entity.Properties.Keys.Where(p => p.StartsWith("d")).OrderBy(p => p)) { var dataPart = entity.Properties[propertyName]; await memoryStream.WriteAsync(dataPart.BinaryValue, 0, dataPart.BinaryValue.Length); } memoryStream.Position = 0; using (var bsonReader = new BsonReader(memoryStream)) { var data = serializer.Deserialize<Dictionary<string, object>>(bsonReader); grainState.SetAll(data); } } }
public async Task WriteStateAsync(string grainType, GrainReference grainReference, IGrainState grainState) { try { var collection = await this.EnsureCollection(grainType); var documents = await this.Client.ReadDocumentFeedAsync(collection.DocumentsLink); var documentId = grainReference.ToKeyString(); var document = documents.Where(d => d.Id == documentId).FirstOrDefault(); if(document != null) { document.State = grainState.AsDictionary(); await this.Client.ReplaceDocumentAsync(document); } else { await this.Client.CreateDocumentAsync(collection.DocumentsLink, new GrainStateDocument { Id = documentId, State = grainState.AsDictionary() }); } } catch (Exception ex) { Log.Error(0, "Error in WriteStateAsync", ex); } }
public async Task ReadStateAsync(string grainType, GrainReference grainReference, IGrainState grainState) { if (!(grainState is IAggregateState)) throw new NotAggregateStateException(grainState.GetType()); var stream = this.GetStreamName(grainType, grainReference); var sliceStart = 0; StreamEventsSlice currentSlice; do { var sliceCount = sliceStart + ReadPageSize; currentSlice = await this.Connection.ReadStreamEventsForwardAsync(stream, sliceStart, sliceCount, true); if (currentSlice.Status == SliceReadStatus.StreamNotFound) return; if (currentSlice.Status == SliceReadStatus.StreamDeleted) throw new StreamDeletedException(); sliceStart = currentSlice.NextEventNumber; foreach (var @event in currentSlice.Events) { dynamic deserialisedEvent = DeserializeEvent(@event.Event); StateTransformer.ApplyEvent(deserialisedEvent, grainState as IAggregateState); } } while (!currentSlice.IsEndOfStream); }
public async Task ReadStateAsync(string grainType, GrainReference grainId, IGrainState grainState) { try { var blobName = BlobStorageProvider.GetBlobName(grainType, grainId); var blob = container.GetBlockBlobReference(blobName); var text = await blob.DownloadTextAsync(); if (string.IsNullOrWhiteSpace(text)) { return; } var data = JsonConvert.DeserializeObject(text, grainState.GetType()); var dict = ((IGrainState)data).AsDictionary(); grainState.SetAll(dict); } catch (StorageException ex) { ; } catch (Exception ex) { Log.Error(0, ex.ToString()); } }
public Task<string> WriteStateAsync(string stateStore, string grainStoreKey, IGrainState grainState) { if (logger.IsVerbose) logger.Verbose("WriteStateAsync for {0} grain: {1} eTag: {2}", stateStore, grainStoreKey, grainState.ETag); GrainStateStore storage = GetStoreForGrain(stateStore); storage.UpdateGrainState(grainStoreKey, grainState); if (logger.IsVerbose) logger.Verbose("Done WriteStateAsync for {0} grain: {1} eTag: {2}", stateStore, grainStoreKey, grainState.ETag); return Task.FromResult(grainState.ETag); }
/// <summary> /// Reads persisted state from the backing store and deserializes it into the the target /// grain state object. /// </summary> /// <param name="grainType">A string holding the name of the grain class.</param> /// <param name="grainReference">Represents the long-lived identity of the grain.</param> /// <param name="grainState">A reference to an object to hold the persisted state of the grain.</param> /// <returns>Completion promise for this operation.</returns> public async Task ReadStateAsync(string grainType, GrainReference grainReference, IGrainState grainState) { if (DataManager == null) throw new ArgumentException("DataManager property not initialized"); var entityData = await DataManager.Read(grainState.GetType().Name, grainReference.ToKeyString()); if (entityData != null) { ConvertFromStorageFormat(grainState, entityData); } }
public Task ClearStateAsync(string grainType, GrainReference grainReference, IGrainState grainState) { if (!(grainState is IAggregateState)) throw new NotAggregateStateException(grainState.GetType()); var state = grainState as IAggregateState; var stream = this.GetStreamName(grainType, grainReference); return this.Connection.DeleteStreamAsync(stream, state.Version); }
public async Task WriteStateAsync(string grainType, GrainReference grainId, IGrainState grainState) { try { var blobName = BlobStorageProvider.GetBlobName(grainType, grainId); var storedData = JsonConvert.SerializeObject(grainState.AsDictionary()); var blob = container.GetBlockBlobReference(blobName); await blob.UploadTextAsync(storedData); } catch (Exception ex) { Log.Error(0, ex.ToString()); } }
public async Task ReadStateAsync(string grainType, GrainReference grainReference, IGrainState grainState) { var stateName = grainState.GetType().Name; var key = grainReference.ToKeyString(); var id = string.Format(CultureInfo.InvariantCulture, "{0}/{1}", stateName, key); using (IAsyncDocumentSession session = this.documentStore.OpenAsyncSession()) { var state = await session.LoadAsync<RavenJObject>(id); if (state != null) { grainState.SetAll(state.ToDictionary(x => x.Key, x => x.Value.Value<object>())); } } }
public async Task ReadStateAsync(string grainType, GrainReference grainReference, IGrainState grainState) { try { var collection = await this.EnsureCollection(grainType); var documents = await this.Client.ReadDocumentFeedAsync(collection.DocumentsLink); var documentId = grainReference.ToKeyString(); GrainStateDocument document = documents.Where(d => d.Id == documentId).FirstOrDefault(); if(document != null) grainState.SetAll(document.State); } catch (Exception ex) { Log.Error(0, "Error in ReadStateAsync", ex); } }
public Task WriteStateAsync(string grainType, GrainReference grainReference, IGrainState grainState) { var entity = new DynamicTableEntity(grainReference.ToKeyString(), grainType) { ETag = "*" }; var serializer = new JsonSerializer(); using (var memoryStream = new MemoryStream()) { using (var bsonWriter = new BsonWriter(memoryStream)) { serializer.Serialize(bsonWriter, grainState.AsDictionary()); SplitBinaryData(entity, memoryStream.ToArray()); } } return _table.ExecuteAsync(TableOperation.InsertOrReplace(entity)); }
/// <summary> Write state data function for this storage provider without /// checking for ETag before update (if there already exists a prior state). </summary> /// <see cref="IExtendedStorageProvider.WriteStateWithoutEtagCheckAsync"/> public async Task WriteStateWithoutEtagCheckAsync(string grainType, GrainReference grainId, IGrainState grainState) { var blobName = GetBlobName(grainType, grainId); try { if (this.Log.IsVerbose3) { this.Log.Verbose3((int)AzureProviderErrorCode.AzureBlobProvider_Storage_Writing, "Writing: GrainType={0} Grainid={1} ETag={2} to BlobName={3} in Container={4}", grainType, grainId, grainState.ETag, blobName, container.Name); } var json = JsonConvert.SerializeObject(grainState.State, jsonSettings); var blob = container.GetBlockBlobReference(blobName); blob.Properties.ContentType = "application/json"; var containerNotFound = false; try { await blob.UploadTextAsync( json, Encoding.UTF8, null, null, null).ConfigureAwait(false); } catch (StorageException exception) { var errorCode = exception.RequestInformation.ExtendedErrorInformation.ErrorCode; containerNotFound = errorCode == BlobErrorCodeStrings.ContainerNotFound; } if (containerNotFound) { // if the container does not exist, create it, and make another attempt if (this.Log.IsVerbose3) { this.Log.Verbose3((int)AzureProviderErrorCode.AzureBlobProvider_ContainerNotFound, "Creating container: GrainType={0} Grainid={1} ETag={2} to BlobName={3} in Container={4}", grainType, grainId, grainState.ETag, blobName, container.Name); } await container.CreateIfNotExistsAsync().ConfigureAwait(false); await blob.UploadTextAsync( json, Encoding.UTF8, null, null, null).ConfigureAwait(false); } grainState.ETag = blob.Properties.ETag; if (this.Log.IsVerbose3) { this.Log.Verbose3((int)AzureProviderErrorCode.AzureBlobProvider_Storage_DataRead, "Written: GrainType={0} Grainid={1} ETag={2} to BlobName={3} in Container={4}", grainType, grainId, grainState.ETag, blobName, container.Name); } } catch (Exception ex) { Log.Error((int)AzureProviderErrorCode.AzureBlobProvider_WriteError, string.Format("Error writing: GrainType={0} Grainid={1} ETag={2} to BlobName={3} in Container={4} Exception={5}", grainType, grainId, grainState.ETag, blobName, container.Name, ex.Message), ex); throw; } }
/// <summary> Clear state data function for this storage provider. </summary> /// <remarks> /// </remarks> /// <see cref="IStorageProvider#ClearStateAsync"/> public async Task ClearStateAsync(string grainType, GrainReference grainReference, IGrainState grainState) { var primaryKey = grainReference.ToKeyString(); try { if (Log.IsVerbose3) { Log.Verbose3((int)SimpleSQLServerProviderErrorCodes.SimpleSQLServerProvider_ClearingData, $"Clearing: GrainType={grainType} Pk={primaryKey} Grainid={grainReference} ETag={grainState.ETag} from DataSource={this.sqlconnBuilder.DataSource} Catalog={this.sqlconnBuilder.InitialCatalog}"); } var entity = new KeyValueStore() { GrainKeyId = primaryKey }; using (var conn = new SqlConnection(this.sqlconnBuilder.ConnectionString)) using (var db = new KeyValueDbContext(conn, true)) { db.KeyValues.Attach(entity); db.KeyValues.Remove(entity); await db.SaveChangesAsync(); grainState.ETag = null; //if(grainState.State is GrainState) // ((GrainState)grainState.State).Etag = null; } } catch (DbUpdateConcurrencyException conCurrenyEx) { //someone has deleted has this record already Log.Error((int)SimpleSQLServerProviderErrorCodes.SimpleSQLServerProvider_DeleteError, $"DbUpdateConcurrencyException ---- we will ignore this Error clearing: GrainType={grainType} GrainId={grainReference} ETag={grainState.ETag} in to DataSource={this.sqlconnBuilder.DataSource + "." + this.sqlconnBuilder.InitialCatalog}", conCurrenyEx); //dont throw --- move on } catch (Exception ex) { Log.Error((int)SimpleSQLServerProviderErrorCodes.SimpleSQLServerProvider_DeleteError, $"Error clearing: GrainType={grainType} GrainId={grainReference} ETag={grainState.ETag} in to DataSource={this.sqlconnBuilder.DataSource + "." + this.sqlconnBuilder.InitialCatalog}", ex); throw; } }
public void Deserialize(IGrainState grainState, JObject entityData) { var jsonReader = new JTokenReader(entityData); serializer.Populate(jsonReader, grainState.State); }
/// <summary> Read state data function for this storage provider. </summary> /// <see cref="IStorageProvider.ReadStateAsync"/> public async Task ReadStateAsync(string grainType, GrainReference grainReference, IGrainState grainState) { if (tableDataManager == null) { throw new ArgumentException("GrainState-Table property not initialized"); } string pk = GetKeyString(grainReference); if (Log.IsVerbose3) { Log.Verbose3((int)AzureProviderErrorCode.AzureTableProvider_ReadingData, "Reading: GrainType={0} Pk={1} Grainid={2} from Table={3}", grainType, pk, grainReference, tableName); } string partitionKey = pk; string rowKey = grainType; GrainStateRecord record = await tableDataManager.Read(partitionKey, rowKey).ConfigureAwait(false); if (record != null) { var entity = record.Entity; if (entity != null) { var loadedState = ConvertFromStorageFormat(entity); grainState.State = loadedState ?? Activator.CreateInstance(grainState.State.GetType()); grainState.ETag = record.ETag; } } // Else leave grainState in previous default condition }
/// <summary> Read state data function for this storage provider. </summary> /// <see cref="IStorageProvider.ReadStateAsync"/> public async Task ReadStateAsync(string grainType, GrainReference grainReference, IGrainState grainState) { if (storage == null) throw new ArgumentException("GrainState-Table property not initialized"); string partitionKey = GetKeyString(grainReference); if (Log.IsVerbose3) Log.Verbose3(ErrorCode.StorageProviderBase, "Reading: GrainType={0} Pk={1} Grainid={2} from Table={3}", grainType, partitionKey, grainReference, tableName); string rowKey = AWSUtils.ValidateDynamoDBRowKey(grainType); var record = await storage.ReadSingleEntryAsync(tableName, new Dictionary<string, AttributeValue> { { GRAIN_REFERENCE_PROPERTY_NAME, new AttributeValue(partitionKey) }, { GRAIN_TYPE_PROPERTY_NAME, new AttributeValue(rowKey) } }, (fields) => { return new GrainStateRecord { GrainType = fields[GRAIN_TYPE_PROPERTY_NAME].S, GrainReference = fields[GRAIN_REFERENCE_PROPERTY_NAME].S, ETag = int.Parse(fields[ETAG_PROPERTY_NAME].N), BinaryState = fields.ContainsKey(BINARY_STATE_PROPERTY_NAME) ? fields[BINARY_STATE_PROPERTY_NAME].B.ToArray() : null, StringState = fields.ContainsKey(STRING_STATE_PROPERTY_NAME) ? fields[STRING_STATE_PROPERTY_NAME].S : string.Empty }; }).ConfigureAwait(false); if (record != null) { var loadedState = ConvertFromStorageFormat(record); grainState.State = loadedState ?? Activator.CreateInstance(grainState.State.GetType()); grainState.ETag = record.ETag.ToString(); } // Else leave grainState in previous default condition }
public async Task ReadStateAsync(string grainType, GrainReference grainReference, IGrainState grainState) { var id = this.GetPrimaryKeyObject(grainReference).ToString(); grainState.State = await this.GetRepository(grainState).ReadAsync(id); }
/// <summary> Write state data function for this storage provider. </summary> /// <see cref="IStorageProvider#WriteStateAsync"/> public virtual async Task WriteStateAsync(string grainType, GrainReference grainReference, IGrainState grainState) { var keys = MakeKeys(grainType, grainReference); var data = grainState.AsDictionary(); string receivedEtag = grainState.Etag; if (Log.IsVerbose2) { Log.Verbose2("Write {0} ", StorageProviderUtils.PrintOneWrite(keys, data, receivedEtag)); } if (receivedEtag != null && receivedEtag != etag) { throw new InconsistentStateException(string.Format("Etag mismatch durign Write: Expected = {0} Received = {1}", etag, receivedEtag)); } string key = HierarchicalKeyStore.MakeStoreKey(keys); IMemoryStorageGrain storageGrain = GetStorageGrain(key); await storageGrain.WriteStateAsync(STATE_STORE_NAME, key, data); etag = NewEtag(); }
/// <summary> Delete / Clear state data function for this storage provider. </summary> /// <see cref="IStorageProvider#ClearStateAsync"/> public virtual async Task ClearStateAsync(string grainType, GrainReference grainReference, IGrainState grainState) { var keys = MakeKeys(grainType, grainReference); string eTag = grainState.Etag; // TOD: Should this be 'null' for always Delete? if (Log.IsVerbose2) { Log.Verbose2("Delete Keys={0} Etag={1}", StorageProviderUtils.PrintKeys(keys), eTag); } if (eTag != null && eTag != etag) { throw new InconsistentStateException(string.Format("Etag mismatch durign Delete: Expected = {0} Received = {1}", this.etag, eTag)); } string key = HierarchicalKeyStore.MakeStoreKey(keys); IMemoryStorageGrain storageGrain = GetStorageGrain(key); await storageGrain.DeleteStateAsync(STATE_STORE_NAME, key); etag = NewEtag(); }
public Task ClearStateAsync(string grainType, GrainReference grainReference, IGrainState grainState) => Task.CompletedTask;
/// <summary> Read state data function for this storage provider. </summary> /// <see cref="IStorageProvider#ReadStateAsync"/> public virtual async Task ReadStateAsync(string grainType, GrainReference grainReference, IGrainState grainState) { var keys = MakeKeys(grainType, grainReference); if (Log.IsVerbose2) { Log.Verbose2("Read Keys={0}", StorageProviderUtils.PrintKeys(keys)); } string id = HierarchicalKeyStore.MakeStoreKey(keys); IMemoryStorageGrain storageGrain = GetStorageGrain(id); IDictionary <string, object> state = await storageGrain.ReadStateAsync(STATE_STORE_NAME, id); grainState.SetAll(state); }
/// <summary> Delete / Clear state data function for this storage provider. </summary> /// <see cref="IStorageProvider.ClearStateAsync"/> public override async Task ClearStateAsync(string grainType, GrainReference grainReference, IGrainState grainState) { await MakeFixedLatencyCall(() => base.ClearStateAsync(grainType, grainReference, grainState)); }
public AppUISettingsGrain(IGrainState <State> state) { Guard.NotNull(state, nameof(state)); this.state = state; }
/// <summary> Write state data function for this storage provider. </summary> /// <see cref="IGrainStorage.WriteStateAsync"/> public async Task WriteStateAsync(string grainType, GrainReference grainReference, IGrainState grainState) { await MakeFixedLatencyCall(() => baseGranStorage.WriteStateAsync(grainType, grainReference, grainState)); }
/// <summary> Read state data function for this storage provider. </summary> /// <see cref="IStorageProvider#ReadStateAsync"/> public async Task ReadStateAsync(string grainType, GrainReference grainReference, IGrainState grainState) { var primaryKey = grainReference.ToKeyString(); if (Log.IsVerbose3) { Log.Verbose3((int) SimpleSQLServerProviderErrorCodes.SimpleSQLServerProvider_ReadingData, $"Reading: GrainType={grainType} Pk={primaryKey} Grainid={grainReference} from DataSource={this.sqlconnBuilder.DataSource + "." + this.sqlconnBuilder.InitialCatalog}"); } try { using (var db = new KeyValueDbContext(this.sqlconnBuilder.ConnectionString)) { switch (this.useJsonOrBinaryFormat) { case StorageFormatEnum.Binary: case StorageFormatEnum.Both: { var value = await db.KeyValues.Where(s => s.GrainKeyId.Equals(primaryKey)).Select(s => new { s.BinaryContent, s.ETag } ).SingleOrDefaultAsync(); if (value != null) { //data = SerializationManager.DeserializeFromByteArray<Dictionary<string, object>>(value); grainState.State = SerializationManager.DeserializeFromByteArray<object>(value.BinaryContent); grainState.ETag = value.ETag; if(grainState.State is GrainState) ((GrainState)grainState.State).Etag = value.ETag; } } break; case StorageFormatEnum.Json: { var value = await db.KeyValues.Where(s => s.GrainKeyId.Equals(primaryKey)).Select(s => new { s.JsonContext, s.ETag }).SingleOrDefaultAsync(); if (value != null && !string.IsNullOrEmpty(value.JsonContext)) { //data = JsonConvert.DeserializeObject<Dictionary<string, object>>(value, jsonSettings); grainState.State = JsonConvert.DeserializeObject(value.JsonContext, grainState.State.GetType(), jsonSettings); grainState.ETag = value.ETag; if(grainState.State is GrainState) ((GrainState)grainState.State).Etag = value.ETag; } } break; default: break; } } } catch (Exception ex) { Log.Error((int) SimpleSQLServerProviderErrorCodes.SimpleSQLServerProvider_ReadError, $"Error reading: GrainType={grainType} Grainid={grainReference} ETag={grainState.ETag} from DataSource={this.sqlconnBuilder.DataSource + "." + this.sqlconnBuilder.InitialCatalog}", ex); throw; } }
public AppsByUserIndexGrain(IGrainState <GrainState> state) { Guard.NotNull(state, nameof(state)); this.state = state; }
public Task ClearStateAsync(string grainType, GrainReference grainReference, IGrainState grainState) => TaskDone.Done;
public async Task WriteStateAsync(string grainType, GrainReference grainReference, IGrainState grainState) { var id = this.GetPrimaryKeyObject(grainReference).ToString(); await this.GetRepository(grainState).WriteAsync(id, grainState.State); }
private async Task WriteStateInternal(IGrainState grainState, GrainStateRecord record, bool clear = false) { var fields = new Dictionary<string, AttributeValue>(); if (record.BinaryState != null && record.BinaryState.Length > 0) { fields.Add(BINARY_STATE_PROPERTY_NAME, new AttributeValue { B = new MemoryStream(record.BinaryState) }); } else if (!string.IsNullOrWhiteSpace(record.StringState)) { fields.Add(STRING_STATE_PROPERTY_NAME, new AttributeValue(record.StringState)); } int newEtag = 0; if (clear) { fields.Add(GRAIN_REFERENCE_PROPERTY_NAME, new AttributeValue(record.GrainReference)); fields.Add(GRAIN_TYPE_PROPERTY_NAME, new AttributeValue(record.GrainType)); int currentEtag = 0; int.TryParse(grainState.ETag, out currentEtag); newEtag = currentEtag; fields.Add(ETAG_PROPERTY_NAME, new AttributeValue { N = newEtag++.ToString() }); await storage.PutEntryAsync(tableName, fields).ConfigureAwait(false); } else if (string.IsNullOrWhiteSpace(grainState.ETag)) { fields.Add(GRAIN_REFERENCE_PROPERTY_NAME, new AttributeValue(record.GrainReference)); fields.Add(GRAIN_TYPE_PROPERTY_NAME, new AttributeValue(record.GrainType)); fields.Add(ETAG_PROPERTY_NAME, new AttributeValue { N = "0" }); var expression = $"attribute_not_exists({GRAIN_REFERENCE_PROPERTY_NAME}) AND attribute_not_exists({GRAIN_TYPE_PROPERTY_NAME})"; await storage.PutEntryAsync(tableName, fields, expression).ConfigureAwait(false); } else { var keys = new Dictionary<string, AttributeValue>(); keys.Add(GRAIN_REFERENCE_PROPERTY_NAME, new AttributeValue(record.GrainReference)); keys.Add(GRAIN_TYPE_PROPERTY_NAME, new AttributeValue(record.GrainType)); int currentEtag = 0; int.TryParse(grainState.ETag, out currentEtag); newEtag = currentEtag; newEtag++; fields.Add(ETAG_PROPERTY_NAME, new AttributeValue { N = newEtag.ToString() }); var conditionalValues = new Dictionary<string, AttributeValue> { { CURRENT_ETAG_ALIAS, new AttributeValue { N = currentEtag.ToString() } } }; var expression = $"{ETAG_PROPERTY_NAME} = {CURRENT_ETAG_ALIAS}"; await storage.UpsertEntryAsync(tableName, keys, fields, expression, conditionalValues).ConfigureAwait(false); } grainState.ETag = newEtag.ToString(); }
/// <summary> Read state data function for this storage provider. </summary> /// <see cref="IStorageProvider.ReadStateAsync"/> public async Task ReadStateAsync(string grainType, GrainReference grainReference, IGrainState grainState) { if (tableDataManager == null) throw new ArgumentException("GrainState-Table property not initialized"); string pk = GetKeyString(grainReference); if (Log.IsVerbose3) Log.Verbose3((int)AzureProviderErrorCode.AzureTableProvider_ReadingData, "Reading: GrainType={0} Pk={1} Grainid={2} from Table={3}", grainType, pk, grainReference, tableName); string partitionKey = pk; string rowKey = grainType; GrainStateRecord record = await tableDataManager.Read(partitionKey, rowKey); if (record != null) { var entity = record.Entity; if (entity != null) { ConvertFromStorageFormat(grainState, entity); grainState.Etag = record.ETag; } } // Else leave grainState in previous default condition }
/// <summary> Clear / Delete state data function for this storage provider. </summary> /// <remarks> /// If the <c>DeleteStateOnClear</c> is set to <c>true</c> then the table row /// for this grain will be deleted / removed, otherwise the table row will be /// cleared by overwriting with default / null values. /// </remarks> /// <see cref="IStorageProvider.ClearStateAsync"/> public async Task ClearStateAsync(string grainType, GrainReference grainReference, IGrainState grainState) { if (storage == null) { throw new ArgumentException("GrainState-Table property not initialized"); } string partitionKey = GetKeyString(grainReference); if (Log.IsVerbose3) { Log.Verbose3(ErrorCode.StorageProviderBase, "Clearing: GrainType={0} Pk={1} Grainid={2} ETag={3} DeleteStateOnClear={4} from Table={5}", grainType, partitionKey, grainReference, grainState.ETag, isDeleteStateOnClear, tableName); } string rowKey = AWSUtils.ValidateDynamoDBRowKey(grainType); var record = new GrainStateRecord { GrainReference = partitionKey, ETag = string.IsNullOrWhiteSpace(grainState.ETag) ? 0 : int.Parse(grainState.ETag), GrainType = rowKey }; var operation = "Clearing"; try { if (isDeleteStateOnClear) { operation = "Deleting"; var keys = new Dictionary <string, AttributeValue>(); keys.Add(GRAIN_REFERENCE_PROPERTY_NAME, new AttributeValue(record.GrainReference)); keys.Add(GRAIN_TYPE_PROPERTY_NAME, new AttributeValue(record.GrainType)); await storage.DeleteEntryAsync(tableName, keys).ConfigureAwait(false); grainState.ETag = string.Empty; } else { await WriteStateInternal(grainState, record, true); } } catch (Exception exc) { Log.Error(ErrorCode.StorageProviderBase, string.Format("Error {0}: GrainType={1} Grainid={2} ETag={3} from Table={4} Exception={5}", operation, grainType, grainReference, grainState.ETag, tableName, exc.Message), exc); throw; } }
/// <summary> Clear / Delete state data function for this storage provider. </summary> /// <remarks> /// If the <c>DeleteStateOnClear</c> is set to <c>true</c> then the table row /// for this grain will be deleted / removed, otherwise the table row will be /// cleared by overwriting with default / null values. /// </remarks> /// <see cref="IStorageProvider.ClearStateAsync"/> public async Task ClearStateAsync(string grainType, GrainReference grainReference, IGrainState grainState) { if (tableDataManager == null) throw new ArgumentException("GrainState-Table property not initialized"); string pk = GetKeyString(grainReference); if (Log.IsVerbose3) Log.Verbose3((int)AzureProviderErrorCode.AzureTableProvider_WritingData, "Clearing: GrainType={0} Pk={1} Grainid={2} ETag={3} DeleteStateOnClear={4} from Table={5}", grainType, pk, grainReference, grainState.Etag, isDeleteStateOnClear, tableName); var entity = new GrainStateEntity { PartitionKey = pk, RowKey = grainType }; var record = new GrainStateRecord { Entity = entity, ETag = grainState.Etag }; string operation = "Clearing"; try { if (isDeleteStateOnClear) { operation = "Deleting"; await tableDataManager.Delete(record); } else { await tableDataManager.Write(record); } grainState.Etag = record.ETag; // Update in-memory data to the new ETag } catch (Exception exc) { Log.Error((int)AzureProviderErrorCode.AzureTableProvider_DeleteError, string.Format("Error {0}: GrainType={1} Grainid={2} ETag={3} from Table={4} Exception={5}", operation, grainType, grainReference, grainState.Etag, tableName, exc.Message), exc); throw; } }
public JObject Serialize(IGrainState grainState) { return(JObject.FromObject(grainState.State, serializer)); }
/// <summary> /// Deserialize from Azure storage format /// </summary> /// <param name="grainState">The grain state data to be deserialized in to</param> /// <param name="entity">The Azure table entity the stored data</param> internal void ConvertFromStorageFormat(IGrainState grainState, GrainStateEntity entity) { Dictionary<string, object> dataValues = null; try { if (entity.Data != null) { // Rehydrate dataValues = SerializationManager.DeserializeFromByteArray<Dictionary<string, object>>(entity.Data); } else if (entity.StringData != null) { dataValues = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, object>>(entity.StringData, jsonSettings); } if (dataValues != null) { grainState.SetAll(dataValues); } // Else, no data found } catch (Exception exc) { var sb = new StringBuilder(); if (entity.Data != null) { sb.AppendFormat("Unable to convert from storage format GrainStateEntity.Data={0}", entity.Data); } else if (entity.StringData != null) { sb.AppendFormat("Unable to convert from storage format GrainStateEntity.StringData={0}", entity.StringData); } if (dataValues != null) { int i = 1; foreach (var dvKey in dataValues.Keys) { object dvValue = dataValues[dvKey]; sb.AppendLine(); sb.AppendFormat("Data #{0} Key={1} Value={2} Type={3}", i, dvKey, dvValue, dvValue.GetType()); i++; } } Log.Error(0, sb.ToString(), exc); throw new AggregateException(sb.ToString(), exc); } }
public async override Task WriteStateAsync(string grainType, GrainReference grainReference, IGrainState grainState) { logger.Info(0, "WriteStateAsync for {0} {1} ErrorInjection={0}", grainType, grainReference, ErrorInjection); try { ThrowIfMatches(ErrorInjectionPoint.BeforeWrite); await base.WriteStateAsync(grainType, grainReference, grainState); ThrowIfMatches(ErrorInjectionPoint.AfterWrite); } catch (Exception exc) { logger.Warn(0, "Injected error during WriteStateAsync for {0} {1} Exception = {2}", grainType, grainReference, exc); throw; } }
/// <summary> Write state data function for this storage provider. </summary> /// <see cref="IStorageProvider.WriteStateAsync"/> public async Task WriteStateAsync(string grainType, GrainReference grainId, IGrainState grainState) { var blobName = GetBlobName(grainType, grainId); try { if (this.Log.IsVerbose3) this.Log.Verbose3((int)AzureProviderErrorCode.AzureBlobProvider_Storage_Writing, "Writing: GrainType={0} Grainid={1} ETag={2} to BlobName={3} in Container={4}", grainType, grainId, grainState.ETag, blobName, container.Name); var json = JsonConvert.SerializeObject(grainState.State, settings); var blob = container.GetBlockBlobReference(blobName); blob.Properties.ContentType = "application/json"; var containerNotFound = false; try { await blob.UploadTextAsync( json, Encoding.UTF8, AccessCondition.GenerateIfMatchCondition(grainState.ETag), null, null).ConfigureAwait(false); } catch (StorageException exception) { var errorCode = exception.RequestInformation.ExtendedErrorInformation.ErrorCode; containerNotFound = errorCode == BlobErrorCodeStrings.ContainerNotFound; } if (containerNotFound) { // if the container does not exist, create it, and make another attempt if (this.Log.IsVerbose3) this.Log.Verbose3((int)AzureProviderErrorCode.AzureBlobProvider_ContainerNotFound, "Creating container: GrainType={0} Grainid={1} ETag={2} to BlobName={3} in Container={4}", grainType, grainId, grainState.ETag, blobName, container.Name); await container.CreateIfNotExistsAsync().ConfigureAwait(false); await blob.UploadTextAsync( json, Encoding.UTF8, AccessCondition.GenerateIfMatchCondition(grainState.ETag), null, null).ConfigureAwait(false); } grainState.ETag = blob.Properties.ETag; if (this.Log.IsVerbose3) this.Log.Verbose3((int)AzureProviderErrorCode.AzureBlobProvider_Storage_DataRead, "Written: GrainType={0} Grainid={1} ETag={2} to BlobName={3} in Container={4}", grainType, grainId, grainState.ETag, blobName, container.Name); } catch (Exception ex) { Log.Error((int)AzureProviderErrorCode.AzureBlobProvider_WriteError, string.Format("Error writing: GrainType={0} Grainid={1} ETag={2} to BlobName={3} in Container={4} Exception={5}", grainType, grainId, grainState.ETag, blobName, container.Name, ex.Message), ex); } }
public Task ClearStateAsync(string grainType, Orleans.Runtime.GrainReference grainReference, IGrainState grainState) { var fileInfo = GetFileInfo(grainType, grainReference); fileInfo.Delete(); return(TaskDone.Done); }
/// <summary> Write state data function for this storage provider. </summary> /// <see cref="IStorageProvider#WriteStateAsync"/> public async Task WriteStateAsync(string grainType, GrainReference grainReference, IGrainState grainState) { if(grainState.State is GrainState) //WARN: HACK, such a hack grainState.ETag = ((GrainState)grainState.State).Etag; var primaryKey = grainReference.ToKeyString(); if (Log.IsVerbose3) { Log.Verbose3((int) SimpleSQLServerProviderErrorCodes.SimpleSQLServerProvider_WritingData, $"Writing: GrainType={grainType} PrimaryKey={primaryKey} GrainId={grainReference} ETag={grainState.ETag} to DataSource={this.sqlconnBuilder.DataSource + "." + this.sqlconnBuilder.InitialCatalog}"); } try { var data = grainState.State; byte[] payload = null; string jsonpayload = string.Empty; if (this.useJsonOrBinaryFormat != StorageFormatEnum.Json) { payload = SerializationManager.SerializeToByteArray(data); } if (this.useJsonOrBinaryFormat == StorageFormatEnum.Json || this.useJsonOrBinaryFormat == StorageFormatEnum.Both) { jsonpayload = JsonConvert.SerializeObject(data, jsonSettings); } var kvb = new KeyValueStore() { JsonContext = jsonpayload, BinaryContent = payload, GrainKeyId = primaryKey, ETag = Guid.NewGuid().ToString() }; using (var db = new KeyValueDbContext(this.sqlconnBuilder.ConnectionString)) { if(grainState.ETag != null) { var value = await db.KeyValues.Where(s => s.GrainKeyId.Equals(primaryKey)).Select(s => s.ETag).SingleOrDefaultAsync(); if(value != null && value != grainState.ETag) { string error = $"Etag mismatch during WriteStateAsync for grain {primaryKey}: Expected = {value ?? "null"} Received = {grainState.ETag}"; Log.Error(0, error); throw new InconsistentStateException(error); } } db.Set<KeyValueStore>().AddOrUpdate(kvb); grainState.ETag = kvb.ETag; if(grainState.State is GrainState) ((GrainState)grainState.State).Etag = kvb.ETag; await db.SaveChangesAsync(); } } catch (Exception ex) { Log.Error((int) SimpleSQLServerProviderErrorCodes.SimpleSQLServerProvider_WriteError, $"Error writing: GrainType={grainType} GrainId={grainReference} ETag={grainState.ETag} to DataSource={this.sqlconnBuilder.DataSource + "." + this.sqlconnBuilder.InitialCatalog}", ex); throw; } }
public Task WriteStateAsync(string grainType, GrainReference grainReference, IGrainState grainState) { return(DoAndLog(nameof(WriteStateAsync), async() => { var grainCollection = GetCollection(grainType); var grainKey = grainReference.ToKeyString(); var grainData = serializer.Serialize(grainState); var etag = grainState.ETag; var newData = grainData.ToBson(); var newETag = Guid.NewGuid().ToString(); try { UpdateOptions update = new UpdateOptions { IsUpsert = true }; await grainCollection.UpdateOneAsync( Filter.And( Filter.Eq(FieldId, grainKey), Filter.Eq(FieldEtag, grainState.ETag) ), Update .Set(FieldEtag, newETag) .Set(FieldDoc, newData), update); } catch (MongoException ex) { if (ex.IsDuplicateKey()) { await ThrowForOtherEtag(grainCollection, grainKey, etag, ex); var document = new BsonDocument { [FieldId] = grainKey, [FieldEtag] = grainKey, [FieldDoc] = newData }; try { await grainCollection.ReplaceOneAsync(Filter.Eq(FieldId, grainKey), document, Upsert); } catch (MongoException ex2) { if (ex2.IsDuplicateKey()) { await ThrowForOtherEtag(grainCollection, grainKey, etag, ex2); } else { throw; } } } else { throw; } } grainState.ETag = newETag; })); }
/// <summary> Read state data function for this storage provider. </summary> /// <see cref="IStorageProvider.ReadStateAsync"/> public async Task ReadStateAsync(string grainType, GrainReference grainId, IGrainState grainState) { var blobName = GetBlobName(grainType, grainId); if (this.Log.IsVerbose3) { this.Log.Verbose3((int)AzureProviderErrorCode.AzureBlobProvider_Storage_Reading, "Reading: GrainType={0} Grainid={1} ETag={2} from BlobName={3} in Container={4}", grainType, grainId, grainState.ETag, blobName, container.Name); } try { var blob = container.GetBlockBlobReference(blobName); string json; try { json = await blob.DownloadTextAsync().ConfigureAwait(false); } catch (StorageException exception) { var errorCode = exception.RequestInformation.ExtendedErrorInformation?.ErrorCode; if (errorCode == BlobErrorCodeStrings.BlobNotFound) { if (this.Log.IsVerbose2) { this.Log.Verbose2((int)AzureProviderErrorCode.AzureBlobProvider_BlobNotFound, "BlobNotFound reading: GrainType={0} Grainid={1} ETag={2} from BlobName={3} in Container={4}", grainType, grainId, grainState.ETag, blobName, container.Name); } return; } if (errorCode == BlobErrorCodeStrings.ContainerNotFound) { if (this.Log.IsVerbose2) { this.Log.Verbose2((int)AzureProviderErrorCode.AzureBlobProvider_ContainerNotFound, "ContainerNotFound reading: GrainType={0} Grainid={1} ETag={2} from BlobName={3} in Container={4}", grainType, grainId, grainState.ETag, blobName, container.Name); } return; } throw; } if (string.IsNullOrWhiteSpace(json)) { if (this.Log.IsVerbose2) { this.Log.Verbose2((int)AzureProviderErrorCode.AzureBlobProvider_BlobEmpty, "BlobEmpty reading: GrainType={0} Grainid={1} ETag={2} from BlobName={3} in Container={4}", grainType, grainId, grainState.ETag, blobName, container.Name); } return; } grainState.State = JsonConvert.DeserializeObject(json, grainState.State.GetType(), jsonSettings); grainState.ETag = blob.Properties.ETag; if (this.Log.IsVerbose3) { this.Log.Verbose3((int)AzureProviderErrorCode.AzureBlobProvider_Storage_DataRead, "Read: GrainType={0} Grainid={1} ETag={2} from BlobName={3} in Container={4}", grainType, grainId, grainState.ETag, blobName, container.Name); } } catch (Exception ex) { Log.Error((int)AzureProviderErrorCode.AzureBlobProvider_ReadError, string.Format("Error reading: GrainType={0} Grainid={1} ETag={2} from BlobName={3} in Container={4} Exception={5}", grainType, grainId, grainState.ETag, blobName, container.Name, ex.Message), ex); throw; } }
/// <summary> Write state data function for this storage provider.</summary> /// <see cref="IStorageProvider.WriteStateAsync"/> public async Task WriteStateAsync(string grainType, GrainReference grainReference, IGrainState grainState) { //It assumed these parameters are always valid. If not, an exception will be thrown, even if not as clear //as with explicitly checked parameters. var data = grainState.State; var grainId = GrainIdAndExtensionAsString(grainReference); var baseGrainType = ExtractBaseClass(grainType); if(Log.IsVerbose3) { Log.Verbose3((int)RelationalStorageProviderCodes.RelationalProviderWriting, LogString("Writing grain state", ServiceId, Name, grainState.ETag, baseGrainType, grainId.ToString())); } string storageVersion = null; try { var writeRecord = await Storage.ReadAsync(CurrentOperationalQueries.WriteToStorage, command => { command.AddParameter("GrainIdHash", HashPicker.PickHasher(ServiceId, Name, baseGrainType, grainReference, grainState).Hash(grainId.GetHashBytes())); command.AddParameter("GrainIdN0", grainId.N0Key); command.AddParameter("GrainIdN1", grainId.N1Key); command.AddParameter("GrainTypeHash", HashPicker.PickHasher(ServiceId, Name, baseGrainType, grainReference, grainState).Hash(Encoding.UTF8.GetBytes(baseGrainType))); command.AddParameter("GrainTypeString", (string)baseGrainType); command.AddParameter("GrainIdExtensionString", grainId.StringKey); command.AddParameter("ServiceId", ServiceId); command.AddParameter("GrainStateVersion", !string.IsNullOrWhiteSpace(grainState.ETag) ? int.Parse(grainState.ETag, CultureInfo.InvariantCulture) : default(int?)); SerializationChoice serializer = StorageSerializationPicker.PickSerializer(ServiceId, Name, (string)baseGrainType, grainReference, grainState); command.AddParameter("PayloadBinary", (byte[])(serializer.Serializer.Tag == UseBinaryFormatPropertyName ? serializer.Serializer.Serialize(data) : null)); command.AddParameter("PayloadJson", (string)(serializer.Serializer.Tag == UseJsonFormatPropertyName ? serializer.Serializer.Serialize(data) : null)); command.AddParameter("PayloadXml", (string)(serializer.Serializer.Tag == UseXmlFormatPropertyName ? serializer.Serializer.Serialize(data) : null)); }, (selector, resultSetCount, token) => { return Task.FromResult(selector.GetValueOrDefault<int?>("NewGrainStateVersion").ToString()); }, CancellationToken.None).ConfigureAwait(false); storageVersion = writeRecord.SingleOrDefault(); } catch(Exception ex) { Log.Error((int)RelationalStorageProviderCodes.RelationalProviderWriteError, LogString("Error writing grain state", ServiceId, Name, grainState.ETag, baseGrainType, grainId.ToString(), ex.Message), ex); throw; } const string OperationString = "WriteState"; var inconsistentStateException = CheckVersionInconsistency(OperationString, ServiceId, Name, storageVersion, grainState.ETag, baseGrainType, grainId.ToString()); if(inconsistentStateException != null) { throw inconsistentStateException; } //No errors found, the version of the state held by the grain can be updated. grainState.ETag = storageVersion; if(Log.IsVerbose3) { Log.Verbose3((int)RelationalStorageProviderCodes.RelationalProviderWrote, LogString("Wrote grain state", ServiceId, Name, grainState.ETag, baseGrainType, grainId.ToString())); } }
/// <summary> Clear / Delete state data function for this storage provider. </summary> /// <remarks> /// If the <c>DeleteStateOnClear</c> is set to <c>true</c> then the table row /// for this grain will be deleted / removed, otherwise the table row will be /// cleared by overwriting with default / null values. /// </remarks> /// <see cref="IStorageProvider.ClearStateAsync"/> public async Task ClearStateAsync(string grainType, GrainReference grainReference, IGrainState grainState) { if (tableDataManager == null) { throw new ArgumentException("GrainState-Table property not initialized"); } string pk = GetKeyString(grainReference); if (logger.IsEnabled(LogLevel.Trace)) { logger.Trace((int)AzureProviderErrorCode.AzureTableProvider_WritingData, "Clearing: GrainType={0} Pk={1} Grainid={2} ETag={3} DeleteStateOnClear={4} from Table={5}", grainType, pk, grainReference, grainState.ETag, this.options.DeleteStateOnClear, this.options.TableName); } var entity = new DynamicTableEntity(pk, grainType); var record = new GrainStateRecord { Entity = entity, ETag = grainState.ETag }; string operation = "Clearing"; try { if (this.options.DeleteStateOnClear) { operation = "Deleting"; await DoOptimisticUpdate(() => tableDataManager.Delete(record), grainType, grainReference, this.options.TableName, grainState.ETag).ConfigureAwait(false); } else { await DoOptimisticUpdate(() => tableDataManager.Write(record), grainType, grainReference, this.options.TableName, grainState.ETag).ConfigureAwait(false); } grainState.ETag = record.ETag; // Update in-memory data to the new ETag } catch (Exception exc) { logger.Error((int)AzureProviderErrorCode.AzureTableProvider_DeleteError, string.Format("Error {0}: GrainType={1} Grainid={2} ETag={3} from Table={4} Exception={5}", operation, grainType, grainReference, grainState.ETag, this.options.TableName, exc.Message), exc); throw; } }
/// <summary> Write state data function for this storage provider. </summary> /// <see cref="IStorageProvider.WriteStateAsync"/> public async Task WriteStateAsync(string grainType, GrainReference grainReference, IGrainState grainState) { if (tableDataManager == null) throw new ArgumentException("GrainState-Table property not initialized"); string pk = GetKeyString(grainReference); if (Log.IsVerbose3) Log.Verbose3((int)AzureProviderErrorCode.AzureTableProvider_WritingData, "Writing: GrainType={0} Pk={1} Grainid={2} ETag={3} to Table={4}", grainType, pk, grainReference, grainState.Etag, tableName); var entity = new GrainStateEntity { PartitionKey = pk, RowKey = grainType }; ConvertToStorageFormat(grainState, entity); var record = new GrainStateRecord { Entity = entity, ETag = grainState.Etag }; try { await tableDataManager.Write(record); grainState.Etag = record.ETag; } catch (Exception exc) { Log.Error((int)AzureProviderErrorCode.AzureTableProvider_WriteError, string.Format("Error Writing: GrainType={0} Grainid={1} ETag={2} to Table={3} Exception={4}", grainType, grainReference, grainState.Etag, tableName, exc.Message), exc); throw; } }
/// <summary> Write state data function for this storage provider. </summary> /// <see cref="IStorageProvider.WriteStateAsync"/> public async Task WriteStateAsync(string grainType, GrainReference grainReference, IGrainState grainState) { if (tableDataManager == null) { throw new ArgumentException("GrainState-Table property not initialized"); } string pk = GetKeyString(grainReference); if (logger.IsEnabled(LogLevel.Trace)) { logger.Trace((int)AzureProviderErrorCode.AzureTableProvider_WritingData, "Writing: GrainType={0} Pk={1} Grainid={2} ETag={3} to Table={4}", grainType, pk, grainReference, grainState.ETag, this.options.TableName); } var entity = new DynamicTableEntity(pk, grainType); ConvertToStorageFormat(grainState.State, entity); var record = new GrainStateRecord { Entity = entity, ETag = grainState.ETag }; try { await DoOptimisticUpdate(() => tableDataManager.Write(record), grainType, grainReference, this.options.TableName, grainState.ETag).ConfigureAwait(false); grainState.ETag = record.ETag; } catch (Exception exc) { logger.Error((int)AzureProviderErrorCode.AzureTableProvider_WriteError, $"Error Writing: GrainType={grainType} Grainid={grainReference} ETag={grainState.ETag} to Table={this.options.TableName} Exception={exc.Message}", exc); throw; } }
/// <summary> /// Serialize to Azure storage format in either binary or JSON format. /// </summary> /// <param name="grainState">The grain state data to be serialized</param> /// <param name="entity">The Azure table entity the data should be stored in</param> /// <remarks> /// See: /// http://msdn.microsoft.com/en-us/library/system.web.script.serialization.javascriptserializer.aspx /// for more on the JSON serializer. /// </remarks> internal void ConvertToStorageFormat(IGrainState grainState, GrainStateEntity entity) { // Dehydrate var dataValues = grainState.AsDictionary(); int dataSize; if (useJsonFormat) { // http://james.newtonking.com/json/help/index.html?topic=html/T_Newtonsoft_Json_JsonConvert.htm string data = Newtonsoft.Json.JsonConvert.SerializeObject(dataValues, jsonSettings); if (Log.IsVerbose3) Log.Verbose3("Writing JSON data size = {0} for grain id = Partition={1} / Row={2}", data.Length, entity.PartitionKey, entity.RowKey); dataSize = data.Length; entity.StringData = data; } else { // Convert to binary format byte[] data = SerializationManager.SerializeToByteArray(dataValues); if (Log.IsVerbose3) Log.Verbose3("Writing binary data size = {0} for grain id = Partition={1} / Row={2}", data.Length, entity.PartitionKey, entity.RowKey); dataSize = data.Length; entity.Data = data; } if (dataSize > MAX_DATA_SIZE) { var msg = string.Format("Data too large to write to Azure table. Size={0} MaxSize={1}", dataSize, MAX_DATA_SIZE); Log.Error(0, msg); throw new ArgumentOutOfRangeException("GrainState.Size", msg); } }
public async Task ReadStateAsync(string grainType, GrainReference grainReference, IGrainState grainState) { if (this._cosmos == null) { throw new ArgumentException("GrainState collection not initialized."); } string id = this.GetKeyString(grainReference); string partitionKey = await this.BuildPartitionKey(grainType, grainReference); if (this._logger.IsEnabled(LogLevel.Trace)) { this._logger.Trace( "Reading: GrainType={0} Key={1} Grainid={2} from Collection={3} with PartitionKey={4}", grainType, id, grainReference, this._options.Collection, partitionKey); } try { var doc = await ExecuteWithRetries(async() => await this._container.ReadItemAsync <GrainStateEntity>( id, new PartitionKey(partitionKey))).ConfigureAwait(false); if (doc.Resource.State != null) { grainState.State = JsonConvert.DeserializeObject(doc.Resource.State.ToString(), grainState.State.GetType(), this._options.JsonSerializerSettings); } else { grainState.State = Activator.CreateInstance(grainState.State.GetType()); } grainState.ETag = doc.Resource.ETag; } catch (CosmosException dce) { if (dce.StatusCode == HttpStatusCode.NotFound) { // State is new, just activate a default and return grainState.State = Activator.CreateInstance(grainState.State.GetType()); return; } this._logger.LogError(dce, $"Failure reading state for Grain Type {grainType} with Id {id}."); throw dce; } catch (Exception exc) { this._logger.LogError(exc, $"Failure reading state for Grain Type {grainType} with Id {id}."); throw; } }
/// <summary> Read state data function for this storage provider. </summary> /// <see cref="IStorageProvider.ReadStateAsync"/> public async Task ReadStateAsync(string grainType, GrainReference grainId, IGrainState grainState) { var blobName = GetBlobName(grainType, grainId); if (this.Log.IsVerbose3) this.Log.Verbose3((int)AzureProviderErrorCode.AzureBlobProvider_Storage_Reading, "Reading: GrainType={0} Grainid={1} ETag={2} from BlobName={3} in Container={4}", grainType, grainId, grainState.ETag, blobName, container.Name); try { var blob = container.GetBlockBlobReference(blobName); string json; try { json = await blob.DownloadTextAsync().ConfigureAwait(false); } catch (StorageException exception) { var errorCode = exception.RequestInformation.ExtendedErrorInformation.ErrorCode; if (errorCode == BlobErrorCodeStrings.BlobNotFound) { if (this.Log.IsVerbose2) this.Log.Verbose2((int)AzureProviderErrorCode.AzureBlobProvider_BlobNotFound, "BlobNotFound reading: GrainType={0} Grainid={1} ETag={2} from BlobName={3} in Container={4}", grainType, grainId, grainState.ETag, blobName, container.Name); return; } if (errorCode == BlobErrorCodeStrings.ContainerNotFound) { if (this.Log.IsVerbose2) this.Log.Verbose2((int)AzureProviderErrorCode.AzureBlobProvider_ContainerNotFound, "ContainerNotFound reading: GrainType={0} Grainid={1} ETag={2} from BlobName={3} in Container={4}", grainType, grainId, grainState.ETag, blobName, container.Name); return; } throw; } if (string.IsNullOrWhiteSpace(json)) { if (this.Log.IsVerbose2) this.Log.Verbose2((int)AzureProviderErrorCode.AzureBlobProvider_BlobEmpty, "BlobEmpty reading: GrainType={0} Grainid={1} ETag={2} from BlobName={3} in Container={4}", grainType, grainId, grainState.ETag, blobName, container.Name); return; } grainState.State = JsonConvert.DeserializeObject(json, grainState.State.GetType(), settings); grainState.ETag = blob.Properties.ETag; if (this.Log.IsVerbose3) this.Log.Verbose3((int)AzureProviderErrorCode.AzureBlobProvider_Storage_DataRead, "Read: GrainType={0} Grainid={1} ETag={2} from BlobName={3} in Container={4}", grainType, grainId, grainState.ETag, blobName, container.Name); } catch (Exception ex) { Log.Error((int)AzureProviderErrorCode.AzureBlobProvider_ReadError, string.Format("Error reading: GrainType={0} Grainid={1} ETag={2} from BlobName={3} in Container={4} Exception={5}", grainType, grainId, grainState.ETag, blobName, container.Name, ex.Message), ex); } }
public async Task WriteStateAsync(string grainType, GrainReference grainReference, IGrainState grainState) { if (this._cosmos == null) { throw new ArgumentException("GrainState collection not initialized."); } string id = this.GetKeyString(grainReference); string partitionKey = await this.BuildPartitionKey(grainType, grainReference); if (this._logger.IsEnabled(LogLevel.Trace)) { this._logger.Trace( "Writing: GrainType={0} Key={1} Grainid={2} ETag={3} from Collection={4} with PartitionKey={5}", grainType, id, grainReference, grainState.ETag, this._options.Collection, partitionKey); } ItemResponse <GrainStateEntity> response = null; try { var entity = new GrainStateEntity { ETag = grainState.ETag, Id = id, GrainType = grainType, State = grainState.State, PartitionKey = partitionKey }; if (string.IsNullOrWhiteSpace(grainState.ETag)) { response = await ExecuteWithRetries(() => this._container.CreateItemAsync( entity, new PartitionKey(partitionKey))).ConfigureAwait(false); grainState.ETag = response.Resource.ETag; } else { response = await ExecuteWithRetries(() => this._container.ReplaceItemAsync( entity, entity.Id, new PartitionKey(partitionKey), new ItemRequestOptions { IfMatchEtag = grainState.ETag })) .ConfigureAwait(false); grainState.ETag = response.Resource.ETag; } } catch (CosmosException dce) when(dce.StatusCode == HttpStatusCode.PreconditionFailed) { throw new CosmosConditionNotSatisfiedException(grainType, grainReference, this._options.Collection, "Unknown", grainState.ETag, dce); } catch (Exception exc) { this._logger.LogError(exc, $"Failure writing state for Grain Type {grainType} with Id {id}."); throw; } }
/// <summary> Clear / Delete state data function for this storage provider. </summary> /// <see cref="IStorageProvider.ClearStateAsync"/> public async Task ClearStateAsync(string grainType, GrainReference grainId, IGrainState grainState) { var blobName = GetBlobName(grainType, grainId); try { if (this.Log.IsVerbose3) this.Log.Verbose3((int)AzureProviderErrorCode.AzureBlobProvider_ClearingData, "Clearing: GrainType={0} Grainid={1} ETag={2} BlobName={3} in Container={4}", grainType, grainId, grainState.ETag, blobName, container.Name); var blob = container.GetBlockBlobReference(blobName); await blob.DeleteIfExistsAsync( DeleteSnapshotsOption.None, AccessCondition.GenerateIfMatchCondition(grainState.ETag), null, null).ConfigureAwait(false); grainState.ETag = blob.Properties.ETag; if (this.Log.IsVerbose3) this.Log.Verbose3((int)AzureProviderErrorCode.AzureBlobProvider_Cleared, "Cleared: GrainType={0} Grainid={1} ETag={2} BlobName={3} in Container={4}", grainType, grainId, grainState.ETag, blobName, container.Name); } catch (Exception ex) { Log.Error((int)AzureProviderErrorCode.AzureBlobProvider_ClearError, string.Format("Error clearing: GrainType={0} Grainid={1} ETag={2} BlobName={3} in Container={4} Exception={5}", grainType, grainId, grainState.ETag, blobName, container.Name, ex.Message), ex); } }
public async Task ClearStateAsync(string grainType, GrainReference grainReference, IGrainState grainState) { if (this._cosmos == null) { throw new ArgumentException("GrainState collection not initialized."); } string id = this.GetKeyString(grainReference); string partitionKey = await this.BuildPartitionKey(grainType, grainReference); if (this._logger.IsEnabled(LogLevel.Trace)) { this._logger.Trace( "Clearing: GrainType={0} Key={1} Grainid={2} ETag={3} DeleteStateOnClear={4} from Collection={4} with PartitionKey {5}", grainType, id, grainReference, grainState.ETag, this._options.DeleteStateOnClear, this._options.Collection, partitionKey); } var pk = new PartitionKey(partitionKey); var requestOptions = new ItemRequestOptions { IfMatchEtag = grainState.ETag }; try { if (this._options.DeleteStateOnClear) { if (string.IsNullOrWhiteSpace(grainState.ETag)) { return; //state not written } await ExecuteWithRetries(() => this._container.DeleteItemAsync <GrainStateEntity>( id, pk, requestOptions)); grainState.ETag = null; } else { var entity = new GrainStateEntity { ETag = grainState.ETag, Id = id, GrainType = grainType, State = null, PartitionKey = partitionKey }; var response = await ExecuteWithRetries(() => string.IsNullOrWhiteSpace(grainState.ETag)? this._container.CreateItemAsync(entity, pk) : this._container.ReplaceItemAsync(entity, entity.Id, pk, requestOptions)) .ConfigureAwait(false); grainState.ETag = response.Resource.ETag; } } catch (Exception exc) { this._logger.LogError(exc, $"Failure clearing state for Grain Type {grainType} with Id {id}."); throw; } }
/// <summary> Clear state data function for this storage provider. </summary> /// <remarks> /// </remarks> /// <see cref="IStorageProvider#ClearStateAsync"/> public async Task ClearStateAsync(string grainType, GrainReference grainReference, IGrainState grainState) { var primaryKey = grainReference.ToKeyString(); try { if (Log.IsVerbose3) { Log.Verbose3((int) SimpleSQLServerProviderErrorCodes.SimpleSQLServerStorageProvider_ClearingData, $"Clearing: GrainType={grainType} Pk={primaryKey} Grainid={grainReference} ETag={grainState.ETag} from DataSource={this.sqlconnBuilder.DataSource} Catalog={this.sqlconnBuilder.InitialCatalog}"); } var entity = new KeyValueStore() { GrainKeyId = primaryKey }; using (var db = new KeyValueDbContext(this.sqlconnBuilder.ConnectionString)) { db.KeyValues.Attach(entity); db.KeyValues.Remove(entity); grainState.ETag = null; if(grainState.State is GrainState) ((GrainState)grainState.State).Etag = null; await db.SaveChangesAsync(); } } catch (Exception ex) { Log.Error((int) SimpleSQLServerProviderErrorCodes.SimpleSQLServerProvider_DeleteError, $"Error clearing: GrainType={grainType} GrainId={grainReference} ETag={grainState.ETag} in to DataSource={this.sqlconnBuilder.DataSource + "." + this.sqlconnBuilder.InitialCatalog}", ex); throw; } }
/// <summary> Read state data function for this storage provider. </summary> /// <see cref="IGrainStorage.ReadStateAsync"/> public virtual async Task ReadStateAsync(string grainType, GrainReference grainReference, IGrainState grainState) { IList <Tuple <string, string> > keys = MakeKeys(grainType, grainReference).ToList(); if (logger.IsEnabled(LogLevel.Trace)) { logger.Trace("Read Keys={0}", StorageProviderUtils.PrintKeys(keys)); } string id = HierarchicalKeyStore.MakeStoreKey(keys); IMemoryStorageGrain storageGrain = GetStorageGrain(id); var state = await storageGrain.ReadStateAsync(STATE_STORE_NAME, id); if (state != null) { grainState.ETag = state.ETag; grainState.State = state.State; } }
/// <summary> Deleet / Clear state data function for this storage provider. </summary> /// <see cref="IStorageProvider#ClearStateAsync"/> public Task ClearStateAsync(string grainType, GrainReference grainReference, IGrainState grainState) { int num = FindStorageShard(grainType, grainReference); IStorageProvider provider = storageProviders[num]; return provider.ClearStateAsync(grainType, grainReference, grainState); }
/// <summary> Write state data function for this storage provider. </summary> /// <see cref="IGrainStorage.WriteStateAsync"/> public virtual async Task WriteStateAsync(string grainType, GrainReference grainReference, IGrainState grainState) { IList <Tuple <string, string> > keys = MakeKeys(grainType, grainReference).ToList(); string key = HierarchicalKeyStore.MakeStoreKey(keys); if (logger.IsEnabled(LogLevel.Trace)) { logger.Trace("Write {0} ", StorageProviderUtils.PrintOneWrite(keys, grainState.State, grainState.ETag)); } IMemoryStorageGrain storageGrain = GetStorageGrain(key); try { grainState.ETag = await storageGrain.WriteStateAsync(STATE_STORE_NAME, key, grainState); } catch (MemoryStorageEtagMismatchException e) { throw e.AsInconsistentStateException(); } }
public override async Task ClearStateAsync(string grainType, GrainReference grainReference, IGrainState grainState) { await MakeFixedLatencyCall(() => base.ClearStateAsync(grainType, grainReference, grainState)); }
/// <summary> Read state data function for this storage provider. </summary> /// <see cref="IStorageProvider.ReadStateAsync"/> public async Task ReadStateAsync(string grainType, GrainReference grainReference, IGrainState grainState) { if (storage == null) { throw new ArgumentException("GrainState-Table property not initialized"); } string partitionKey = GetKeyString(grainReference); if (Log.IsVerbose3) { Log.Verbose3(ErrorCode.StorageProviderBase, "Reading: GrainType={0} Pk={1} Grainid={2} from Table={3}", grainType, partitionKey, grainReference, tableName); } string rowKey = AWSUtils.ValidateDynamoDBRowKey(grainType); var record = await storage.ReadSingleEntryAsync(tableName, new Dictionary <string, AttributeValue> { { GRAIN_REFERENCE_PROPERTY_NAME, new AttributeValue(partitionKey) }, { GRAIN_TYPE_PROPERTY_NAME, new AttributeValue(rowKey) } }, (fields) => { return(new GrainStateRecord { GrainType = fields[GRAIN_TYPE_PROPERTY_NAME].S, GrainReference = fields[GRAIN_REFERENCE_PROPERTY_NAME].S, ETag = int.Parse(fields[ETAG_PROPERTY_NAME].N), BinaryState = fields.ContainsKey(BINARY_STATE_PROPERTY_NAME) ? fields[BINARY_STATE_PROPERTY_NAME].B.ToArray() : null, StringState = fields.ContainsKey(STRING_STATE_PROPERTY_NAME) ? fields[STRING_STATE_PROPERTY_NAME].S : string.Empty }); }).ConfigureAwait(false); if (record != null) { var loadedState = ConvertFromStorageFormat(record); grainState.State = loadedState ?? Activator.CreateInstance(grainState.State.GetType()); grainState.ETag = record.ETag.ToString(); } // Else leave grainState in previous default condition }
/// <summary> Write state data function for this storage provider. </summary> /// <see cref="IStorageProvider.WriteStateAsync"/> public async Task WriteStateAsync(string grainType, GrainReference grainReference, IGrainState grainState) { if (storage == null) throw new ArgumentException("GrainState-Table property not initialized"); string partitionKey = GetKeyString(grainReference); string rowKey = AWSUtils.ValidateDynamoDBRowKey(grainType); var record = new GrainStateRecord { GrainReference = partitionKey, GrainType = rowKey }; try { ConvertToStorageFormat(grainState.State, record); await WriteStateInternal(grainState, record); } catch (ConditionalCheckFailedException exc) { throw new InconsistentStateException("Invalid grain state", exc); } catch (Exception exc) { Log.Error(ErrorCode.StorageProviderBase, string.Format("Error Writing: GrainType={0} Grainid={1} ETag={2} to Table={3} Exception={4}", grainType, grainReference, grainState.ETag, tableName, exc.Message), exc); throw; } }
/// <summary> Write state data function for this storage provider. </summary> /// <see cref="IStorageProvider.WriteStateAsync"/> public async Task WriteStateAsync(string grainType, GrainReference grainReference, IGrainState grainState) { if (storage == null) { throw new ArgumentException("GrainState-Table property not initialized"); } string partitionKey = GetKeyString(grainReference); string rowKey = AWSUtils.ValidateDynamoDBRowKey(grainType); var record = new GrainStateRecord { GrainReference = partitionKey, GrainType = rowKey }; try { ConvertToStorageFormat(grainState.State, record); await WriteStateInternal(grainState, record); } catch (ConditionalCheckFailedException exc) { throw new InconsistentStateException("Invalid grain state", exc); } catch (Exception exc) { Log.Error(ErrorCode.StorageProviderBase, string.Format("Error Writing: GrainType={0} Grainid={1} ETag={2} to Table={3} Exception={4}", grainType, grainReference, grainState.ETag, tableName, exc.Message), exc); throw; } }
/// <summary> Clear / Delete state data function for this storage provider. </summary> /// <remarks> /// If the <c>DeleteStateOnClear</c> is set to <c>true</c> then the table row /// for this grain will be deleted / removed, otherwise the table row will be /// cleared by overwriting with default / null values. /// </remarks> /// <see cref="IStorageProvider.ClearStateAsync"/> public async Task ClearStateAsync(string grainType, GrainReference grainReference, IGrainState grainState) { if (storage == null) throw new ArgumentException("GrainState-Table property not initialized"); string partitionKey = GetKeyString(grainReference); if (Log.IsVerbose3) Log.Verbose3(ErrorCode.StorageProviderBase, "Clearing: GrainType={0} Pk={1} Grainid={2} ETag={3} DeleteStateOnClear={4} from Table={5}", grainType, partitionKey, grainReference, grainState.ETag, isDeleteStateOnClear, tableName); string rowKey = AWSUtils.ValidateDynamoDBRowKey(grainType); var record = new GrainStateRecord { GrainReference = partitionKey, ETag = string.IsNullOrWhiteSpace(grainState.ETag) ? 0 : int.Parse(grainState.ETag), GrainType = rowKey }; var operation = "Clearing"; try { if (isDeleteStateOnClear) { operation = "Deleting"; var keys = new Dictionary<string, AttributeValue>(); keys.Add(GRAIN_REFERENCE_PROPERTY_NAME, new AttributeValue(record.GrainReference)); keys.Add(GRAIN_TYPE_PROPERTY_NAME, new AttributeValue(record.GrainType)); await storage.DeleteEntryAsync(tableName, keys).ConfigureAwait(false); grainState.ETag = string.Empty; } else { await WriteStateInternal(grainState, record, true); } } catch (Exception exc) { Log.Error(ErrorCode.StorageProviderBase, string.Format("Error {0}: GrainType={1} Grainid={2} ETag={3} from Table={4} Exception={5}", operation, grainType, grainReference, grainState.ETag, tableName, exc.Message), exc); throw; } }
private async Task WriteStateInternal(IGrainState grainState, GrainStateRecord record, bool clear = false) { var fields = new Dictionary <string, AttributeValue>(); if (record.BinaryState != null && record.BinaryState.Length > 0) { fields.Add(BINARY_STATE_PROPERTY_NAME, new AttributeValue { B = new MemoryStream(record.BinaryState) }); } else if (!string.IsNullOrWhiteSpace(record.StringState)) { fields.Add(STRING_STATE_PROPERTY_NAME, new AttributeValue(record.StringState)); } int newEtag = 0; if (clear) { fields.Add(GRAIN_REFERENCE_PROPERTY_NAME, new AttributeValue(record.GrainReference)); fields.Add(GRAIN_TYPE_PROPERTY_NAME, new AttributeValue(record.GrainType)); int currentEtag = 0; int.TryParse(grainState.ETag, out currentEtag); newEtag = currentEtag; fields.Add(ETAG_PROPERTY_NAME, new AttributeValue { N = newEtag++.ToString() }); await storage.PutEntryAsync(tableName, fields).ConfigureAwait(false); } else if (string.IsNullOrWhiteSpace(grainState.ETag)) { fields.Add(GRAIN_REFERENCE_PROPERTY_NAME, new AttributeValue(record.GrainReference)); fields.Add(GRAIN_TYPE_PROPERTY_NAME, new AttributeValue(record.GrainType)); fields.Add(ETAG_PROPERTY_NAME, new AttributeValue { N = "0" }); var expression = $"attribute_not_exists({GRAIN_REFERENCE_PROPERTY_NAME}) AND attribute_not_exists({GRAIN_TYPE_PROPERTY_NAME})"; await storage.PutEntryAsync(tableName, fields, expression).ConfigureAwait(false); } else { var keys = new Dictionary <string, AttributeValue>(); keys.Add(GRAIN_REFERENCE_PROPERTY_NAME, new AttributeValue(record.GrainReference)); keys.Add(GRAIN_TYPE_PROPERTY_NAME, new AttributeValue(record.GrainType)); int currentEtag = 0; int.TryParse(grainState.ETag, out currentEtag); newEtag = currentEtag; newEtag++; fields.Add(ETAG_PROPERTY_NAME, new AttributeValue { N = newEtag.ToString() }); var conditionalValues = new Dictionary <string, AttributeValue> { { CURRENT_ETAG_ALIAS, new AttributeValue { N = currentEtag.ToString() } } }; var expression = $"{ETAG_PROPERTY_NAME} = {CURRENT_ETAG_ALIAS}"; await storage.UpsertEntryAsync(tableName, keys, fields, expression, conditionalValues).ConfigureAwait(false); } grainState.ETag = newEtag.ToString(); }