public Task <BoolResult> RegisterCheckpointAsync(OperationContext context, CheckpointState checkpointState) { TriggerGarbageCollection(context); var msg = checkpointState.ToString(); return(context.PerformOperationWithTimeoutAsync( Tracer, context => { var blobName = GenerateBlobName(); checkpointState.Consumers.TryAdd(_primaryMachineLocation); if (_configuration.WriteLegacyFormat) { return _storage.WriteAsync(context, blobName, JsonSerializer.Serialize(checkpointState, _jsonSerializerOptions)); } else { return _storage.WriteAsync(context, blobName, checkpointState); } }, traceOperationStarted: false, extraStartMessage: msg, extraEndMessage: _ => msg, timeout: _configuration.RegisterCheckpointTimeout)); }
internal Task <BoolResult> GarbageCollectAsync(OperationContext context, int retentionLimit) { Contract.Requires(retentionLimit >= 0); return(context.PerformOperationWithTimeoutAsync( Tracer, async context => { var blobs = ListBlobsRecentFirstAsync(context) .Skip(retentionLimit); await foreach (var blob in blobs) { try { var deleteSucceeded = await _storage.DeleteIfExistsAsync(context, blob); Tracer.Info(context, $"Delete attempt Name=[{blob.Name}] Succeeded=[{deleteSucceeded}]"); } catch (Exception e) { Tracer.Error(context, e, $"Delete attempt Name=[{blob.Name}]"); } } return BoolResult.Success; }, timeout: _configuration.GarbageCollectionTimeout)); }
public Task <Result <CheckpointState> > GetCheckpointStateAsync(OperationContext context) { // NOTE: this function is naturally retried by the heartbeat mechanisms in LLS return(context.PerformOperationWithTimeoutAsync( Tracer, async context => { var blobs = ListBlobsRecentFirstAsync(context); await foreach (var blob in blobs) { try { var checkpointState = await _storage.ReadAsync <CheckpointState>(context, blob).ThrowIfFailureAsync(); checkpointState.FileName = blob; foreach (var consumer in checkpointState.Consumers) { _pushLocations.Add(consumer, _configuration.PushCheckpointCandidateExpiry); } return Result.Success(checkpointState); } catch (TaskCanceledException) when(context.Token.IsCancellationRequested) { // We hit timeout or a proper cancellation. // Breaking from the loop instead of tracing error for each iteration. break; } catch (Exception e) { Tracer.Error(context, e, $"Failed to obtain {nameof(CheckpointState)} from blob `{blob.Name}`. Skipping."); continue; } } // Add slack for start cursor to account for clock skew return CheckpointState.CreateUnavailable(_clock.UtcNow - _configuration.NewEpochEventStartCursorDelay); }, extraEndMessage: result => { if (!result.Succeeded) { return string.Empty; } var checkpointState = result.Value; return $"CheckpointId=[{checkpointState.CheckpointId}] SequencePoint=[{checkpointState.StartSequencePoint}]"; }, timeout: _configuration.CheckpointStateTimeout)); }