public async Task <IEventStream> GetStream <T>(string bucket, Id streamId, IEnumerable <Id> parents = null) where T : class, IEventSource { parents = parents ?? new Id[] { }; var streamName = _streamGen(typeof(T), StreamTypes.Domain, bucket, streamId, parents); Logger.Write(LogLevel.Debug, () => $"Retreiving stream [{streamId}] in bucket [{bucket}] for type {typeof(T).FullName}"); var cached = _cache.Retreive(streamName) as IImmutableEventStream; if (cached != null) { HitMeter.Mark(); Logger.Write(LogLevel.Debug, () => $"Found stream [{streamName}] in cache"); return(new EventStream <T>(cached)); } MissMeter.Mark(); while (await CheckFrozen <T>(bucket, streamId, parents).ConfigureAwait(false)) { Logger.Write(LogLevel.Info, () => $"Stream [{streamId}] in bucket [{bucket}] is frozen - waiting"); await Task.Delay(100).ConfigureAwait(false); } Logger.Write(LogLevel.Debug, () => $"Stream [{streamId}] in bucket [{bucket}] not in cache - reading from store"); ISnapshot snapshot = null; if (typeof(ISnapshotting).IsAssignableFrom(typeof(T))) { snapshot = await _snapstore.GetSnapshot <T>(bucket, streamId, parents).ConfigureAwait(false); Logger.Write(LogLevel.Debug, () => { if (snapshot != null) { return($"Retreived snapshot for entity id [{streamId}] bucket [{bucket}] version {snapshot.Version}"); } return($"No snapshot found for entity id [{streamId}] bucket [{bucket}]"); }); } var events = await _store.GetEvents(streamName, start : snapshot?.Version + 1).ConfigureAwait(false); var oobMetadata = await _store.GetMetadata(streamName, OobMetadataKey).ConfigureAwait(false); IEnumerable <OobDefinition> oobs = null; if (!string.IsNullOrEmpty(oobMetadata)) { oobs = JsonConvert.DeserializeObject <IEnumerable <OobDefinition> >(oobMetadata); } var eventstream = new EventStream <T>(bucket, streamId, parents, oobs, events, snapshot); _cache.Cache(streamName, eventstream.Clone()); Logger.Write(LogLevel.Debug, () => $"Stream [{streamId}] in bucket [{bucket}] read - version is {eventstream.CommitVersion}"); return(eventstream); }