public IObservable <Either <RiakException, RiakObject> > WalkLinks(RiakObject riakObject, IList <RiakLink> riakLinks) { var observables = Observable.Create <Either <RiakException, RiakObject> >(async obs => { try { System.Diagnostics.Debug.Assert(riakLinks.Count > 0, "Link walking requires at least one link"); var input = new RiakBucketKeyInput() .Add(riakObject.Bucket, riakObject.Key); var query = new RiakMapReduceQuery() .Inputs(input); var lastLink = riakLinks.Last(); foreach (var riakLink in riakLinks) { var link = riakLink; var keep = ReferenceEquals(link, lastLink); query.Link(l => l.FromRiakLink(link).Keep(keep)); } var result = await MapReduce(query).ConfigureAwait(false); var linkResults = result.PhaseResults .GroupBy(r => r.Phase) .Where(g => g.Key == riakLinks.Count - 1); var linkResultStrings = linkResults .SelectMany(lr => lr.ToList(), (lr, r) => new { lr, r }) .SelectMany(@t => @t.r.Values, (@t, s) => s.FromRiakString()); //var linkResultStrings = linkResults.SelectMany(g => g.Select(r => r.Values.Value.FromRiakString())); var rawLinks = linkResultStrings .SelectMany(RiakLink.ParseArrayFromJsonString) .Distinct(); var oids = rawLinks .Select(l => new RiakObjectId(l.Bucket, l.Key)) .ToList(); var source = Get(oids, new RiakGetOptions()); return(source.Subscribe(obs.OnNext, obs.OnError, obs.OnCompleted)); } catch (Exception exception) { obs.OnError(exception); } return(Disposable.Empty); }); return(observables); }
public Task <RiakResult <IList <RiakObject> > > WalkLinks(RiakObject riakObject, IList <RiakLink> riakLinks) { System.Diagnostics.Debug.Assert(riakLinks.Count > 0, "Link walking requires at least one link"); var input = new RiakBucketKeyInput(); input.AddBucketKey(riakObject.Bucket, riakObject.Key); var query = new RiakMapReduceQuery() .Inputs(input); var lastLink = riakLinks.Last(); foreach (var riakLink in riakLinks) { var link = riakLink; var keep = ReferenceEquals(link, lastLink); query.Link(l => l.FromRiakLink(link).Keep(keep)); } return(MapReduce(query) .ContinueWith((Task <RiakResult <RiakMapReduceResult> > finishedTask) => { var result = finishedTask.Result; if (result.IsSuccess) { var linkResults = result.Value.PhaseResults.GroupBy(r => r.Phase).Where(g => g.Key == riakLinks.Count - 1); var linkResultStrings = linkResults.SelectMany(lr => lr.ToList(), (lr, r) => new { lr, r }) .SelectMany(@t => @t.r.Values, (@t, s) => s.FromRiakString()); //var linkResultStrings = linkResults.SelectMany(g => g.Select(r => r.Values.Value.FromRiakString())); var rawLinks = linkResultStrings.SelectMany(RiakLink.ParseArrayFromJsonString).Distinct(); var oids = rawLinks.Select(l => new RiakObjectId(l.Bucket, l.Key)).ToList(); return Get(oids, new RiakGetOptions()) .ContinueWith((Task <IEnumerable <RiakResult <RiakObject> > > getTask) => { var objects = getTask.Result; // FIXME // we could be discarding results here. Not good? // This really should be a multi-phase map/reduce return RiakResult <IList <RiakObject> > .Success(objects.Where(r => r.IsSuccess).Select(r => r.Value).ToList()); }); } return RiakResult <IList <RiakObject> > .ErrorTask(result.ResultCode, result.ErrorMessage, result.NodeOffline); }).Unwrap()); }
/// <summary> /// Retrieve arbitrarily deep list of links for a <see cref="RiakObject"/> /// </summary> /// <returns> /// A list of <see cref="RiakObject"/> identified by the list of links. /// </returns> /// <param name='riakObject'> /// The initial object to use for the beginning of the link walking. /// </param> /// <param name='riakLinks'> /// A list of link definitions /// </param> /// <remarks>Refer to http://wiki.basho.com/Links-and-Link-Walking.html for more information.</remarks> public RiakResult <IList <RiakObject> > WalkLinks(RiakObject riakObject, IList <RiakLink> riakLinks) { var input = new RiakBucketKeyInput(); input.AddBucketKey(riakObject.Bucket, riakObject.Key); var query = new RiakMapReduceQuery() .Inputs(input); foreach (var riakLink in riakLinks) { var link = riakLink; var keep = link == riakLinks.Last(); query.Link(l => l.FromRiakLink(link).Keep(keep)); } var result = MapReduce(query); if (result.IsSuccess) { var linkResults = result.Value.PhaseResults.GroupBy(r => r.Phase).Where(g => g.Key == riakLinks.Count - 1); var linkResultStrings = linkResults.SelectMany(lr => lr.ToList(), (lr, r) => new { lr, r }) .SelectMany(@t => @t.r.Values, (@t, s) => s.FromRiakString()); //var linkResultStrings = linkResults.SelectMany(g => g.Select(r => r.Values.Value.FromRiakString())); var rawLinks = linkResultStrings.SelectMany(RiakLink.ParseArrayFromJsonString).Distinct(); var oids = rawLinks.Select(l => new RiakObjectId(l.Bucket, l.Key)).ToList(); var objects = Get(oids); // FIXME // we could be discarding results here. Not good? // This really should be a multi-phase map/reduce return(RiakResult <IList <RiakObject> > .Success(objects.Where(r => r.IsSuccess).Select(r => r.Value).ToList())); } return(RiakResult <IList <RiakObject> > .Error(result.ResultCode, result.ErrorMessage)); }