public async Task<bool> InsertRow(MembershipEntry entry, TableVersion tableVersion) { try { if (logger.IsEnabled(LogLevel.Debug)) logger.Debug("InsertRow entry = {0}", entry.ToFullString()); var tableEntry = Convert(entry); bool result; try { var expression = $"attribute_not_exists({SiloInstanceRecord.DEPLOYMENT_ID_PROPERTY_NAME}) AND attribute_not_exists({SiloInstanceRecord.SILO_IDENTITY_PROPERTY_NAME})"; await storage.PutEntryAsync(TABLE_NAME_DEFAULT_VALUE, tableEntry.GetFields(true), expression); result = true; } catch (ConditionalCheckFailedException) { result = false; logger.Warn(ErrorCode.MembershipBase, $"Insert failed due to contention on the table. Will retry. Entry {entry.ToFullString()}"); } return result; } catch (Exception exc) { logger.Warn(ErrorCode.MembershipBase, $"Intermediate error inserting entry {entry.ToFullString()} to the table {TABLE_NAME_DEFAULT_VALUE}.", exc); throw; } }
private async Task <bool> TryCreateTableVersionEntryAsync() { var keys = new Dictionary <string, AttributeValue> { { $"{SiloInstanceRecord.DEPLOYMENT_ID_PROPERTY_NAME}", new AttributeValue(this.clusterId) }, { $"{SiloInstanceRecord.SILO_IDENTITY_PROPERTY_NAME}", new AttributeValue(SiloInstanceRecord.TABLE_VERSION_ROW) } }; var versionRow = await storage.ReadSingleEntryAsync(this.options.TableName, keys, fields => new SiloInstanceRecord(fields)); if (versionRow != null) { return(false); } if (!TryCreateTableVersionRecord(0, null, out var entry)) { return(false); } var notExistConditionExpression = $"attribute_not_exists({SiloInstanceRecord.DEPLOYMENT_ID_PROPERTY_NAME}) AND attribute_not_exists({SiloInstanceRecord.SILO_IDENTITY_PROPERTY_NAME})"; try { await storage.PutEntryAsync(this.options.TableName, entry.GetFields(true), notExistConditionExpression); } catch (ConditionalCheckFailedException) { return(false); } return(true); }
/// <summary> /// Async method to put an entry into the remider table /// </summary> /// <param name="entry"> The entry to put </param> /// <returns> Return the entry ETag if entry was upsert successfully </returns> public async Task <string> UpsertRow(ReminderEntry entry) { var reminderId = ConstructReminderId(serviceId, entry.GrainRef, entry.ReminderName); var fields = new Dictionary <string, AttributeValue> { { REMINDER_ID_PROPERTY_NAME, new AttributeValue(reminderId) }, { GRAIN_HASH_PROPERTY_NAME, new AttributeValue { N = entry.GrainRef.GetUniformHashCode().ToString() } }, { SERVICE_ID_PROPERTY_NAME, new AttributeValue(serviceId.ToString()) }, { GRAIN_REFERENCE_PROPERTY_NAME, new AttributeValue(entry.GrainRef.ToKeyString()) }, { PERIOD_PROPERTY_NAME, new AttributeValue(entry.Period.ToString()) }, { START_TIME_PROPERTY_NAME, new AttributeValue(entry.StartAt.ToString()) }, { REMINDER_NAME_PROPERTY_NAME, new AttributeValue(entry.ReminderName) }, { ETAG_PROPERTY_NAME, new AttributeValue { N = random.Next(int.MaxValue).ToString() } } }; try { if (logger.IsEnabled(LogLevel.Debug)) { logger.Debug("UpsertRow entry = {0}, etag = {1}", entry.ToString(), entry.ETag); } await storage.PutEntryAsync(TABLE_NAME_DEFAULT_VALUE, fields); entry.ETag = fields[ETAG_PROPERTY_NAME].N; return(entry.ETag); } catch (Exception exc) { logger.Warn(ErrorCode.ReminderServiceBase, $"Intermediate error updating entry {entry.ToString()} to the table {TABLE_NAME_DEFAULT_VALUE}.", 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(); }