private void RemoveExpired(WriteTransaction txn, TableKey tableKey, Timestamp keyExpiry) { //_expirationQueue(txn, _kvTable, key, keyExpiry); var currentClock = _currentClock(); var metadata = new KvMetadata { Status = Expired, Expiry = keyExpiry, Action = Updated, Originated = currentClock, LocallyUpdated = currentClock }; txn.Delete(_kvTable, tableKey); // TODO: Check and fail on not successful return codes _metadataTable.AddOrUpdate(txn, tableKey, metadata); // _kvUpdateHandler(txn, ToDeleteLogEvent(key, metadata)); // TODO: Add EXPIRY-s to the replication log? }
private bool CheckAndRemoveIfExpired(KvKey key, VectorClock currentClock, KvMetadata metadataToCheck, WriteTransaction txn = null) { if (metadataToCheck == null || metadataToCheck.Status == Active && currentClock.TicksOffsetUtc < metadataToCheck.Expiry.TicksOffsetUtc) { return(true); } if (metadataToCheck.Status == Active && currentClock.TicksOffsetUtc < metadataToCheck.Expiry.TicksOffsetUtc) { if (txn != null) { RemoveExpired(txn, ToTableKey(key), metadataToCheck.Expiry); } else { _lmdb.WriteAsync(tx => RemoveExpired(tx, ToTableKey(key), metadataToCheck.Expiry), false); } } return(false); }
public async void CreateCollectionSuccess() { Application application = new Application(EnvironmentHelper.ApiKey("OrchestrateApiKey")); var client = new Client(application); try { dynamic item = new ExpandoObject(); item.Id = 1; string guid = Guid.NewGuid().ToString(); KvMetadata metaData = await client.CreateCollectionAsync(collectionName, guid, item); Assert.Equal(collectionName, metaData.CollectionName); Assert.Equal(guid, metaData.Key); Assert.True(metaData.VersionReference.Length > 0); Assert.Contains(metaData.VersionReference, metaData.Location); } finally { await client.DeleteCollectionAsync(collectionName); } }
public TableValue ToTableValue(KvMetadata metadata) => metadata.ToByteArray();
public bool AddOrUpdate(WriteTransaction txn, TableKey key, KvMetadata metadata) => txn.AddOrUpdate(_table, key, ToTableValue(metadata));
public async Task <ulong> SyncHandler(WriteLogEvent syncEvent) { var posn = syncEvent.LocallySaved.GetReplicaValue(_targetReplicaId); if (!posn.HasValue) { throw new EventLogException($"Broken syncEvent.LocallySaved during replication '{syncEvent.LocallySaved}'. For replica '{_targetReplicaId}'"); } var pos = posn.Value; if (_cancellationToken.IsCancellationRequested) { return(pos); } switch (syncEvent.LoggedEventCase) { case WriteLogEvent.LoggedEventOneofCase.Updated: var addedOrUpdated = syncEvent.Updated; await _lmdb.WriteAsync(txn => { var addMetadata = new KvMetadata { Status = Active, Expiry = addedOrUpdated.Expiry, Action = Replicated, Originated = syncEvent.Originated, ValueMetadata = syncEvent.ValueMetadata, CorrelationId = syncEvent.CorrelationId }; var wasUpdated = _kvTable.Add( txn, new KvKey(addedOrUpdated.Key), addMetadata, new KvValue(addedOrUpdated.Value), (key, vcOld, vcNew) => vcOld.Earlier(vcNew)); _replicationTable.SetLastPos(txn, _targetReplicaId, pos); _kvTable.StatusTable.IncrementCounters(txn, replicatedAdds: 1); // TODO: Should we do anything if the value wasn't updated? Maybe logging? }, false, true); break; case WriteLogEvent.LoggedEventOneofCase.Deleted: var deleted = syncEvent.Deleted; await _lmdb.WriteAsync(txn => { _updateClock(txn, _targetReplicaId, syncEvent.LocallySaved.GetReplicaValue(_targetReplicaId)); var delMetadata = new KvMetadata { Status = KvMetadata.Types.Status.Deleted, Expiry = syncEvent.LocallySaved.TicksOffsetUtc.ToTimestamp(), Action = Replicated, Originated = syncEvent.Originated, OriginatorReplicaId = syncEvent.OriginatorReplicaId, CorrelationId = syncEvent.CorrelationId, ValueMetadata = syncEvent.ValueMetadata, }; var kvKey = new KvKey(deleted.Key); _kvTable.Delete(txn, kvKey, delMetadata); _replicationTable.SetLastPos(txn, _targetReplicaId, pos); _kvTable.StatusTable.IncrementCounters(txn, replicatedDeletes: 1); // TODO: Should we do anything if the value wasn't updated? Maybe logging? }, false, true); break; case WriteLogEvent.LoggedEventOneofCase.None: throw new ArgumentException("syncEvent", $"Unexpected LogEvent case: {syncEvent.LoggedEventCase}"); default: throw new ArgumentOutOfRangeException(); } return(pos); }