public DemandSubscription Run(Demand demand) { // 1. Persist subscription var demandSubscription = this.SubscriptionRepository.CreateDemandSubscription(demand); // 2. Construct the pipeline var pipeline = new SubscriptionPipeline <DemandSubscription, MarketRequestorEvent>() { Subscription = demandSubscription }; this.RequestorEventPipelines.Add(demandSubscription.Id, pipeline); // 3. Resolve the Demand against existing Offer subscriptions and: // - pull the matching ones immediately to pipeline // - ???push the Demand into pipelines of matching Offers??? // this is questionable, as this would "duplicate" the message exchange - // - Providers would receive a "market proposal" from matching, and immediately respond with a counter proposal, // thus the Requestors would almost certainly receive a "market proposal" and a subsequent "direct proposal" // from most Providers (as there are few Requestors and many willing Providers) // - So it is tempting to 'break the symmetry' and not forward the Demand automatically to Provider subscription pipelines. foreach (var offerSubscription in this.ProviderEventPipelines.Values) { var offer = offerSubscription.Subscription.Offer; var matchingResult = this.MarketResolver.MatchDemandOffer(demand.Properties.Select(prop => prop.Key + ((prop.Value == null) ? "" : ("=" + prop.Value))).ToArray(), demand.Constraints, offer.Properties.Select(prop => prop.Key + ((prop.Value == null) ? "" : ("=" + prop.Value))).ToArray(), offer.Constraints); switch (matchingResult) { case GolemMarketResolver.ResultEnum.True: // Persist OfferProposal with var offerProposal = this.ProposalRepository.SaveOfferProposal(demandSubscription.Id, offerSubscription.Subscription.Id, offer); // no "previous proposal id" as we are mathcing the "on market" demands/offers this.OfferSubscriptions.Add(offerProposal.Id, offerSubscription.Subscription.Id); // Build Provider OfferProposal event and put in Requestor pipeline var requestorEvent = new MarketRequestorEvent() { EventType = MarketRequestorEvent.MarketRequestorEventType.Proposal, OfferProposal = offerProposal, ProviderId = offer.NodeId }; if (!pipeline.PipelineQueue.TryAdd(requestorEvent)) { // TODO what do we do if unable to Add (eg. due to collection full)? // Log warning? // Should iteration be stopped now (to allow the Requestor to collect results?) // What about other possible Offers that were skipped? they will not have a chance of being matched again... } break; default: break; } } return(demandSubscription); }
public void Subscribe(SubscriptionPipeline <TMessage> receiver) { async ValueTask Subscription(TMessage message) { var result = await receiver(message).ConfigureAwait(false); if (result == false) { Pipe -= Subscription; } } Pipe += Subscription; }