public static async Task <Tuple <bool, IComposedObject <T> > > CreateAsync([NotNull] ICacheClient redis, [NotNull] T dataObject, CancellationToken cancellationToken) { if (redis == null) { throw new ArgumentNullException(nameof(redis)); } if (dataObject == null) { throw new ArgumentNullException(nameof(dataObject)); } var ret = new ComposedObject <T>(dataObject); var perfect = true; var taskLocation = Task.Run( async() => { var composedLocation = await CacheManager.LookupOrRetrieveAsync <ObjectBase>(dataObject.Location, redis, async(d, token) => await Room.GetAsync(redis, dataObject.Location, token), cancellationToken); ret.Location = composedLocation; perfect = perfect && (dataObject.Location <= 0 || composedLocation != null); }, cancellationToken); if (dataObject.Contents != null) { var contents = new List <IComposedObject <ObjectBase> >(); Parallel.ForEach( dataObject.Contents, async dbref => { var composedContent = await CacheManager.LookupOrRetrieveAsync(dbref, redis, async(d, token) => await ObjectBase.GetAsync(redis, d, token), cancellationToken); if (composedContent != null) { contents.Add(composedContent); } perfect = perfect && (dbref <= 0 || composedContent != null); }); ret.Contents = contents.AsReadOnly(); } var taskParent = Task.Run( async() => { var composedParent = await CacheManager.LookupOrRetrieveAsync(dataObject.Parent, redis, async(d, token) => await ObjectBase.GetAsync(redis, dataObject.Parent, token), cancellationToken); ret.Parent = composedParent; perfect = perfect && (dataObject.Parent <= 0 || composedParent != null); }, cancellationToken); // ReSharper disable once PossibleNullReferenceException await Task.WhenAll(taskLocation, taskParent); return(new Tuple <bool, IComposedObject <T> >(perfect, ret)); }
public static async Task <IComposedObject <T> > LookupOrRetrieveAsync <T>( DbRef reference, [NotNull] ICacheClient redis, [NotNull] Func <DbRef, CancellationToken, Task <T> > retrieveFunction, CancellationToken cancellationToken) where T : ObjectBase { if (reference.Equals(DbRef.Ambiguous) || reference.Equals(DbRef.FailedMatch) || reference.Equals(DbRef.Nothing)) { return(null); } if (redis == null) { throw new ArgumentNullException(nameof(redis)); } if (retrieveFunction == null) { throw new ArgumentNullException(nameof(retrieveFunction)); } if (reference.Equals(DbRef.Nothing)) { return(null); } if (Cache.Contains(reference)) { return((IComposedObject <T>)Cache.Get(reference)); } var obj = await retrieveFunction.Invoke(reference, cancellationToken); if (obj == null) { return(null); } var composition = await ComposedObject <T> .CreateAsync(redis, obj, cancellationToken); if (composition.Item1) { // The composition was perfect! No unresolved references, so cache it as-is. Cache.Add(reference, composition.Item2, Policy); } return(composition.Item2); }
public static async Task <IComposedObject <T> > UpdateAsync <T>( DbRef reference, [NotNull] ICacheClient redis, [NotNull] T updatedDataObject, CancellationToken cancellationToken) where T : ObjectBase { if (Cache.Contains(reference)) { Cache.Remove(reference); } var composition = await ComposedObject <T> .CreateAsync(redis, updatedDataObject, cancellationToken); if (composition.Item1) { // The composition was perfect! No unresolved references, so cache it as-is. Cache.Add(reference, composition.Item2, Policy); } return(composition.Item2); }