/// <summary> /// Store a value in local memory cache and external network cache. /// </summary> /// <param name="key">Cache key (unique within external cache)</param> /// <param name="val">Value serialised as a string</param> /// <param name="absoluteExpiration">Absolute expiration relative to now.</param> public void Set(string key, string val, TimeSpan absoluteExpiration) { StoreLocalMemory(key, val, absoluteExpiration); _traceWriter?.Write($"{nameof(MemoryFrontedExternalCache)}: {nameof(Set)}: {nameof(_externalCache)}.{nameof(_externalCache.StringSet)}(key: {key}, ttl: {absoluteExpiration.TotalSeconds});"); _externalCache.StringSet($"{_cacheKeyPrefixItem}{key}", val, absoluteExpiration); }
/// <summary> /// Ensure a scheduled trigger is setup for the callbacks based on a unique key. /// </summary> /// <param name="key">Unique key of scheduled trigger / item.</param> /// <param name="callbackAction">Action to call back at specified interval.</param> /// <param name="maxInactiveRetention">Amount of time to continue performing call-backs after UpdateLastActivity is called.</param> /// <param name="callbackInterval">Frequency with which to perform callback and schedule next callback.</param> /// <param name="prevCallbackStartTimeUtc">The time the last call to callback, schedules the next callback from the start time of the previous callback/generation of a value.</param> /// <param name="lastActiveUtc">Optional - date/time of last activity seen (must be in utc).</param> /// <param name="traceId">Optional traceId for diagnostics.</param> public void EnsureTriggerScheduled(string key, Action callbackAction, TimeSpan maxInactiveRetention, TimeSpan callbackInterval, DateTime prevCallbackStartTimeUtc, DateTime?lastActiveUtc = null, string traceId = null) { _traceWriter?.Write($"{nameof(ScheduledTriggerManager)}: {nameof(EnsureTriggerScheduled)}: TraceId:{traceId}: Key:{key}"); if (GetCurrentOrRegenerated(key) == null) { // always schedule callback from previousStart + callbackInterval unless cache is going awry (generation taking longer than reGenInterval + tollerance) // in which case schedule regen for a minimum period of time in the future (will then likely fail to get global lock and defer to next result and schedule // further forward). var logicalStartTime = prevCallbackStartTimeUtc.Add(callbackInterval); if (logicalStartTime < DateTime.UtcNow.AddSeconds(MinimumForwardSchedulingSeconds)) { logicalStartTime = DateTime.UtcNow.AddSeconds(MinimumForwardSchedulingSeconds); } var policy = new CacheItemPolicy { // if not scheduled but cache item existed, can we schedule regenration to happen 60 (regen interval) seconds after last seen schedule (any where in farm) // Address edge case where callback at the end of maxInactiveRetention might skip a beat by getting something from cache // but not scheduling the callback untill after it expires. AbsoluteExpiration = logicalStartTime, RemovedCallback = (removeArgs) => ScheduleNextAndInvokeCallBack(removeArgs), }; var triggerInfo = new TriggerInfo { LastActive = lastActiveUtc ?? DateTime.UtcNow, TargetCallbackTime = logicalStartTime, CallBack = callbackAction, MaxInactiveRetention = maxInactiveRetention, CallbackInterval = callbackInterval, TraceId = traceId, }; // only schedule a cleanup task if this thread won the race to add to the dictionary. if (Add(key, triggerInfo, policy)) { // setup a task to reliably cause cache to expire at required time (1 second late to ensure cache invalidation / expiry - // otherwise .net may see the get on the exact second of expiry and regard the item as not expired). // .net will generally do this every 20 seconds for all expired memory cache entries, but this is not documented/gaurenteed // behaviour so it is worth forcing for reliability (a futre .net version could change this behavior such as doing it less // frequently if there is cpu pressure but not memory pressure). var delay = logicalStartTime.Subtract(DateTime.UtcNow).Add(TimeSpan.FromSeconds(TriggerDelaySeconds)); _traceWriter?.Write($"{nameof(ScheduledTriggerManager)}: {nameof(EnsureTriggerScheduled)}: TraceId:{traceId}: Schedule Cleanup: Key:{key}, in {delay.TotalSeconds}s"); Task.Delay(delay).ContinueWith(t => { _traceWriter?.Write($"{nameof(ScheduledTriggerManager)}: {nameof(EnsureTriggerScheduled)}: TraceId:{traceId}: Scheduled Cleanup Executing: Key:{key}"); ClearIfExpired(key); }).ConfigureAwait(false); } } }
internal void Exit() { lock (_locker) { if (_inUse) { _count += 1; TimeSpan elapsed = _timeMeasure.Pause(); _traceWriter.Write(elapsed, _chain, _args); _queue.Enqueue(this); _inUse = false; } } }
public Task Track(Immutable <IBatchContainer> batchContainer) => _traceWriter.Write(batchContainer.Value);
private void WriteTraceEntry(ref TraceEntry traceEntry) { _writer.Write(ref traceEntry); }
protected override void PreProceed(IInvocation invocation) { writer.Write("Enter: {0}", invocation.Method.Name); }
public Task Track(IBatchContainer batchContainer) => _traceWriter.Write(batchContainer);