public override Task <(long commitLogPosition, long inputQueuePosition)> RecoverAsync() { foreach (var guid in this.ReadCheckpointIntentions()) { this.failedCheckpoints.Add(guid); } var tasks = new List <Task>(); // kick off loads for all singletons foreach (var key in TrackedObjectKey.GetSingletons()) { var loadTask = this.LoadAsync(key); this.pendingLoads.Add(key, new PendingLoad() { EffectTracker = null, ReadEvents = new List <PartitionReadEvent>(), LoadTask = loadTask, }); tasks.Add(loadTask); } Task.WhenAll(tasks).GetAwaiter().GetResult(); this.CompletePending(); var dedupState = (DedupState)this.cache[TrackedObjectKey.Dedup].TrackedObject; return(Task.FromResult(dedupState.Positions)); }
public void InitialUpdater(ref Key key, ref EffectTracker tracker, ref Value value) { var trackedObject = TrackedObjectKey.Factory(key.Val); this.stats.Create++; trackedObject.Partition = this.partition; value.Val = trackedObject; tracker.ProcessEffectOn(trackedObject); this.stats.Modify++; }
// create a tracked object on the main session (only one of these is executing at a time) public override ValueTask <TrackedObject> CreateAsync(Key key) { try { TrackedObject newObject = TrackedObjectKey.Factory(key); newObject.Partition = this.partition; Value newValue = newObject; // Note: there is no UpsertAsync(). this.mainSession.Upsert(ref key, ref newValue); return(new ValueTask <TrackedObject>(newObject)); } catch (Exception exception) when(this.terminationToken.IsCancellationRequested && !Utils.IsFatal(exception)) { throw new OperationCanceledException("Partition was terminated.", exception, this.terminationToken); } }
IAsyncEnumerable <OrchestrationState> ScanOrchestrationStates( EffectTracker effectTracker, PartitionQueryEvent queryEvent) { var instanceQuery = queryEvent.InstanceQuery; string queryId = queryEvent.EventIdString; this.partition.EventDetailTracer?.TraceEventProcessingDetail($"starting query {queryId}"); // we use a separate thread to iterate, since Faster can iterate synchronously only at the moment // and we don't want it to block thread pool worker threads var channel = Channel.CreateBounded <OrchestrationState>(500); var scanThread = new Thread(RunScan) { Name = $"QueryScan-{queryId}" }; scanThread.Start(); return(channel.Reader.ReadAllAsync()); void RunScan() { using var _ = EventTraceContext.MakeContext(0, queryId); // get the unique set of keys appearing in the log and emit them using var iter1 = this.fht.Iterate(); Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); long scanned = 0; long deserialized = 0; long matched = 0; long lastReport; void ReportProgress() { this.partition.EventDetailTracer?.TraceEventProcessingDetail( $"query {queryId} scan position={iter1.CurrentAddress} elapsed={stopwatch.Elapsed.TotalSeconds:F2}s scanned={scanned} deserialized={deserialized} matched={matched}"); lastReport = stopwatch.ElapsedMilliseconds; } ReportProgress(); while (iter1.GetNext(out RecordInfo recordInfo) && !recordInfo.Tombstone) { if (stopwatch.ElapsedMilliseconds - lastReport > 5000) { ReportProgress(); } TrackedObjectKey key = iter1.GetKey().Val; if (key.ObjectType == TrackedObjectKey.TrackedObjectType.Instance) { scanned++; //this.partition.EventDetailTracer?.TraceEventProcessingDetail($"found instance {key.InstanceId}"); if (string.IsNullOrEmpty(instanceQuery?.InstanceIdPrefix) || key.InstanceId.StartsWith(instanceQuery.InstanceIdPrefix)) { //this.partition.EventDetailTracer?.TraceEventProcessingDetail($"reading instance {key.InstanceId}"); object val = iter1.GetValue().Val; //this.partition.EventDetailTracer?.TraceEventProcessingDetail($"read instance {key.InstanceId}, is {(val == null ? "null" : val.GetType().Name)}"); InstanceState instanceState; if (val is byte[] bytes) { instanceState = (InstanceState)Serializer.DeserializeTrackedObject(bytes); deserialized++; } else { instanceState = (InstanceState)val; } // reading the orchestrationState may race with updating the orchestration state // but it is benign because the OrchestrationState object is immutable var orchestrationState = instanceState?.OrchestrationState; if (orchestrationState != null && instanceQuery.Matches(orchestrationState)) { matched++; this.partition.EventDetailTracer?.TraceEventProcessingDetail($"match instance {key.InstanceId}"); var value = orchestrationState.ClearFieldsImmutably(!instanceQuery.FetchInput, false); var task = channel.Writer.WriteAsync(value); if (!task.IsCompleted) { task.AsTask().Wait(); } } } } } ReportProgress(); channel.Writer.Complete(); this.partition.EventDetailTracer?.TraceEventProcessingDetail($"finished query {queryId}"); } }