Example #1
0
        public ParseSingleInputStringFormattedAsJSONToInputMessage(CalculateAndStoreFromInputAndAsyncTermsOptions calculateAndStoreFromInputAndAsyncTermsOptions) : base(calculateAndStoreFromInputAndAsyncTermsOptions)
        {
            Log.Trace("Constructor starting");
            // create the output via a TransformBlock
            _transformer = new TransformBlock <string, InputMessage <string, double> >(_input => {
                InputMessage <string, double> im;
                try
                {
                    Log.Trace("Deserialize Starting");
                    im = JsonConvert.DeserializeObject <InputMessage <string, double> >(_input);
                    Log.Trace("Deserialize Finished");
                }
                catch
                {
                    ArgumentException e = new ArgumentException($"{_input} does not match the needed input pattern");
                    Log.WarnException("Exception", e, "unused");
                    throw e;
                }
                return(im);
            });

            RegisterChild(_transformer);
            Log.Trace("Constructor Finished");
        }
Example #2
0
        // Constructor
        public CalculateAndStoreFromInputAndAsyncTerms(CalculateAndStoreFromInputAndAsyncTermsObservableData calculateAndStoreFromInputAndAsyncTermsObservableData, IWebGet webGet, CalculateAndStoreFromInputAndAsyncTermsOptions calculateAndStoreFromInputAndAsyncTermsOptions) : base(calculateAndStoreFromInputAndAsyncTermsOptions)
        {
            Log.Trace("Constructor starting");

            _calculateAndStoreFromInputAndAsyncTermsObservableData = calculateAndStoreFromInputAndAsyncTermsObservableData;
            _webGet = webGet;
            _calculateAndStoreFromInputAndAsyncTermsOptions = calculateAndStoreFromInputAndAsyncTermsOptions;
            // Create a place to store the TransientBuffers that buffer messages while waiting For all elements that make up the ElementSets Of Term1 to finish fetching
            _transientBuffersForElementSetsOfTerm1 = new ConcurrentDictionary <string, Dataflow <IInternalMessage <string>, IInternalMessage <string> > >();

            // foreach IInputMessage<TKeyTerm1,TValueTerm1>, create an internal message that adds the hashset for the terms1  and the bool used by the routing predicate
            Log.Trace("Creating _bAccepter");
            _bAccepter = new TransformBlock <IInputMessage <string, double>, IInternalMessage <string> >(_input => { Log.Trace("Accepter received IInputMessage");
                                                                                                                     // ToDo also check on the async tasks check when an upstream completion occurs
                                                                                                                     // ToDo add exception handling to ensure the tasks, as well as the async method's resources, are released if any blocks in the dataflow fault

                                                                                                                     // create a HashSet from the set of keys found in terms1
                                                                                                                     KeySignature <string> sig = new KeySignature <string>(_input.Value.terms1.Keys);

                                                                                                                     // Is the sig.largest in the ElementSetsOfTerm1Ready dictionary? set the output bool accordingly
                                                                                                                     bool isReadyToCalculate = _calculateAndStoreFromInputAndAsyncTermsObservableData.ElementSetsOfTerm1Ready.ContainsKey(sig.Longest());

                                                                                                                     // Pass the message along to the next block, which will be either the _bSolveStore, or the _bDynamicBuffers
                                                                                                                     return(new InternalMessage <string>((_input.Value.k1, _input.Value.k2, _input.Value.terms1, sig, isReadyToCalculate))); }).ToDataflow();

            // this block accepts messages where isReadyToCalculate is false, and buffers them
            Log.Trace("Creating _bDynamicBuffers");
            _bDynamicBuffers = new DynamicBuffers(this);

            // The terminator block performs both the Solve and the Store operations
            Log.Trace("Creating _bSolveStore");
            _bSolveStore = new ActionBlock <IInternalMessage <string> >(_input => { Log.Trace($"_bSolveStore received InternalMessage having signature {_input.Value.sig.Longest()}");
                                                                                    // solve the equation for the input and all terms
                                                                                    var r1 = 0.0;
                                                                                    foreach (var kvp in _input.Value.terms1)
                                                                                    {
                                                                                        r1 += kvp.Value /
                                                                                              _calculateAndStoreFromInputAndAsyncTermsObservableData.FetchedIndividualElementsOfTerm1[kvp.Key];
                                                                                    }

                                                                                    // Store the results value
                                                                                    calculateAndStoreFromInputAndAsyncTermsObservableData.RecordR(_input.Value.k1,
                                                                                                                                                  _input.Value.k2,
                                                                                                                                                  Convert.ToDecimal(r1)); }).ToDataflow(calculateAndStoreFromInputAndAsyncTermsOptions);


            #region create asyncFetchCheckTimer and connect callback
            // Create a timer that is used to check on the async fetch tasks, the  async fetch tasks check-for-completion loop timer
            // the timer has its interval from the options passed into this constructor, it will restart and the event handler will stop the timer and start the timer each time
            // ToDo add the timer that checks on the health of the async fetch tasks check-for-completion loop every DefaultAsyncFetchTimeout interval, expecting it to provide a heartbeat,
            // The Cleanup method will call this timers Dispose method
            // the event handler's job is to call CheckAsyncTasks which will check for completed fetches and link the child Transient buffers to the _bSolveStore
            Log.Trace("creating and starting the asyncFetchCheckTimer");
            asyncFetchCheckTimer           = new Timer(_calculateAndStoreFromInputAndAsyncTermsOptions.AsyncFetchTimeInterval.TotalMilliseconds);
            asyncFetchCheckTimer.AutoReset = true;
            // set the event handler (callback) for this timer to the function for async fetch tasks check-for-completion loop
            asyncFetchCheckTimer.Elapsed += new ElapsedEventHandler(asyncFetchCheckTimer_Elapsed);
            asyncFetchCheckTimer.Start();
            #endregion create asyncFetchCheckTimer and connect callback
            _bAccepter.Name       = "_bAccepter";
            _bSolveStore.Name     = "_bSolveStore";
            _bDynamicBuffers.Name = "_bDynamicBuffers";

            // Link the data flow
            Log.Trace("Linking dataflow between blocks");
            // Link _bAccepter to _bSolveStore when the InternalMessage.Value has isReadyToCalculate = true
            _bAccepter.LinkTo(_bSolveStore,
                              internalMessage => internalMessage.Value.isReadyToCalculate);
            // Link _bAccepter to _bDynamicBuffers when the  InternalMessage.Value has isReadyToCalculate = false
            _bAccepter.LinkTo(_bDynamicBuffers,
                              internalMessage => !internalMessage.Value.isReadyToCalculate);
            // data flow linkage of the dynamically created TransientBuffer children to the _bSolveStore is complex and handled elsewhere

            // Link the completion tasks
            Log.Trace("Linking completion between blocks");
            _bDynamicBuffers.RegisterDependency(_bAccepter);
            _bSolveStore.RegisterDependency(_bAccepter);
            _bSolveStore.RegisterDependency(_bDynamicBuffers);
            // Completion linkage of the dynamically created TransientBuffer children to the _bSolveStore is complex and handled elsewhere

            Log.Trace("Registering Children");
            this.RegisterChild(_bAccepter);
            this.RegisterChild(_bSolveStore);
            this.RegisterChild(_bDynamicBuffers);

            // set the InputBlock for this dataflow graph to be the InputBlock of the _acceptor
            this._headBlock = _bAccepter.InputBlock;
            // ToDo: add an optional constructor parameter that supplies an initial list of elements that can start pre-fetching for each term
            Log.Trace("Constructor Finished");
        }