Beispiel #1
0
        private void Commands()
        {
            AwaitingSubscription();
            Command <Match>(m => TickerSymbol.Equals(m.StockId), m =>
            {
                _log.Info("Received MATCH for {0} - price: {1} quantity: {2}", TickerSymbol, m.SettlementPrice, m.Quantity);
                if (_matchAggregate == null)
                {
                    _matchAggregate = new MatchAggregate(TickerSymbol, m.SettlementPrice, m.Quantity);
                    return;
                }

                if (!_matchAggregate.WithMatch(m))
                {
                    // should never get to here
                    _log.Warning("Received Match for ticker symbol [{0}] - but we only accept symbols for [{1}]", m.StockId, TickerSymbol);
                }
            });

            // Matches for a different ticker symbol
            Command <Match>(m =>
            {
                _log.Warning("Received Match for ticker symbol [{0}] - but we only accept symbols for [{1}]", m.StockId, TickerSymbol);
            });

            // Command sent to pull down a complete snapshot of active pricing data for this ticker symbol
            Command <FetchPriceAndVolume>(f =>
            {
                // no price data yet
                if (_priceUpdates.Count == 0 || _volumeUpdates.Count == 0)
                {
                    Sender.Tell(PriceAndVolumeSnapshot.Empty(TickerSymbol));
                }
                else
                {
                    Sender.Tell(new PriceAndVolumeSnapshot(TickerSymbol, _priceUpdates.ToArray(), _volumeUpdates.ToArray()));
                }
            });

            Command <PublishEvents>(p =>
            {
                if (_matchAggregate == null)
                {
                    return;
                }

                var(latestPrice, latestVolume) = _matchAggregate.FetchMetrics(_timestamper);

                // Need to update pricing records prior to persisting our state, since this data is included in
                // output of SaveAggregateData()
                _priceUpdates.Add(latestPrice);
                _volumeUpdates.Add(latestVolume);

                PersistAsync(SaveAggregateData(), snapshot =>
                {
                    _log.Info("Saved latest price {0} and volume {1}", snapshot.RecentAvgPrice, snapshot.RecentAvgVolume);
                    if (LastSequenceNr % SnapshotEveryN == 0)
                    {
                        SaveSnapshot(snapshot);
                    }
                });

                // publish updates to price and volume subscribers
                _marketEventPublisher.Publish(TickerSymbol, latestPrice);
                _marketEventPublisher.Publish(TickerSymbol, latestVolume);
            });

            Command <Ping>(p =>
            {
                if (_log.IsDebugEnabled)
                {
                    _log.Debug("pinged via {0}", Sender);
                }
            });

            Command <SaveSnapshotSuccess>(s =>
            {
                // clean-up prior snapshots and journal events
                DeleteSnapshots(new SnapshotSelectionCriteria(s.Metadata.SequenceNr - 1));
                DeleteMessages(s.Metadata.SequenceNr);
            });

            /*
             * Handle subscriptions directly in case we're using in-memory, local pub-sub.
             */
            CommandAsync <MarketSubscribe>(async sub =>
            {
                try
                {
                    var ack = await _marketEventSubscriptionManager.Subscribe(TickerSymbol, sub.Events, sub.Subscriber);
                    Context.Watch(sub.Subscriber);
                    sub.Subscriber.Tell(ack);
                    Sender.Tell(ack); // need this for ASK operations.
                }
                catch (Exception ex)
                {
                    _log.Error(ex, "Error while processing subscription {0}", sub);
                    sub.Subscriber.Tell(new MarketSubscribeNack(TickerSymbol, sub.Events, ex.Message));
                }
            });

            CommandAsync <MarketUnsubscribe>(async unsub =>
            {
                try
                {
                    var ack = await _marketEventSubscriptionManager.Unsubscribe(PersistenceId, unsub.Events, unsub.Subscriber);
                    // leave DeathWatch intact, in case actor is still subscribed to additional topics
                    unsub.Subscriber.Tell(ack);
                    Sender.Tell(ack); // need this for ASK operations.
                }
                catch (Exception ex)
                {
                    _log.Error(ex, "Error while processing unsubscribe {0}", unsub);
                    unsub.Subscriber.Tell(new MarketUnsubscribeNack(TickerSymbol, unsub.Events, ex.Message));
                }
            });

            CommandAsync <Terminated>(async t =>
            {
                try
                {
                    var ack = await _marketEventSubscriptionManager.Unsubscribe(TickerSymbol, t.ActorRef);
                }
                catch (Exception ex)
                {
                    _log.Error(ex, "Error while processing unsubscribe for terminated subscriber {0} for symbol {1}", t.ActorRef, TickerSymbol);
                }
            });
        }
Beispiel #2
0
        private void Commands()
        {
            Command <EventEnvelope>(e =>
            {
                if (e.Event is Match m)
                {
                    // update the offset
                    if (e.Offset is Sequence s)
                    {
                        QueryOffset = s.Value;
                    }

                    if (_matchAggregate == null)
                    {
                        _matchAggregate = new MatchAggregate(TickerSymbol, m.SettlementPrice, m.Quantity);
                        return;
                    }

                    if (!_matchAggregate.WithMatch(m))
                    {
                        _log.Warning("Received Match for ticker symbol [{0}] - but we only accept symbols for [{1}]", m.StockId, TickerSymbol);
                    }
                }
            });

            // Command sent by a PriceViewActor to pull down a complete snapshot of active pricing data
            Command <FetchPriceAndVolume>(f =>
            {
                // no price data yet
                if (_priceUpdates.Count == 0 || _volumeUpdates.Count == 0)
                {
                    Sender.Tell(PriceAndVolumeSnapshot.Empty(TickerSymbol));
                }
                else
                {
                    Sender.Tell(new PriceAndVolumeSnapshot(TickerSymbol, _priceUpdates.ToArray(), _volumeUpdates.ToArray()));
                }
            });

            Command <PublishEvents>(p =>
            {
                if (_matchAggregate == null)
                {
                    return;
                }

                var(latestPrice, latestVolume) = _matchAggregate.FetchMetrics(_timestamper);

                // Need to update pricing records prior to persisting our state, since this data is included in
                // output of SaveAggregateData()
                _priceUpdates.Add(latestPrice);
                _volumeUpdates.Add(latestVolume);

                PersistAsync(SaveAggregateData(), snapshot =>
                {
                    _log.Info("Saved latest price {0} and volume {1}", snapshot.AvgPrice, snapshot.AvgVolume);
                    if (LastSequenceNr % SnapshotEveryN == 0)
                    {
                        SaveSnapshot(snapshot);
                    }
                });

                // publish updates to in-memory replicas
                _mediator.Tell(new Publish(_priceTopic, latestPrice));
                _mediator.Tell(new Publish(_volumeTopic, latestVolume));
            });

            Command <Ping>(p =>
            {
                if (_log.IsDebugEnabled)
                {
                    _log.Debug("pinged via {0}", Sender);
                }
            });

            Command <SaveSnapshotSuccess>(s =>
            {
                // clean-up prior snapshots and journal events
                DeleteSnapshots(new SnapshotSelectionCriteria(s.Metadata.SequenceNr - 1));
                DeleteMessages(s.Metadata.SequenceNr);
            });
        }