internal void ResourceOnStreamEvent(object sender, StreamEventArgs streamEventArgs) { // Note that we can have only one update at time // as the current SDK's threading model calls this // method using always the same thread (per object basis) try { var deltaMessage = streamEventArgs.Update.FromJson<StreamMessage>(); var fixtureDelta = deltaMessage.GetContent<Fixture>(); _logger.InfoFormat("{0} stream update arrived", fixtureDelta); if (IsDisposing) { _logger.WarnFormat("Listener for {0} is disposing - skipping current update", _resource); return; } if (!AquireLock()) { _logger.WarnFormat("Failed to acquire lock while trying to process stream update {0}", fixtureDelta); return; } RaiseEvent(OnBeginStreamUpdateProcessing, null, fixtureDelta); if (IsDisposing) { _logger.WarnFormat("Listener for {0} is disposing - skipping current update", _resource); return; } // if there was an error from which we haven't recovered yet // it might be that with a new sequence, we might recover. // So in this case, ignore the update and grab a new // snapshot. if (IsErrored) { _logger.DebugFormat("Listener for {0} was in an error state - skipping update and grabbing a new snapshot", _resource); IsErrored = false; RetrieveAndProcessSnapshot(); return; } if (!IsSequenceValid(fixtureDelta)) { _logger.WarnFormat("Update for {0} will not be processed because sequence is not valid", fixtureDelta); // if snapshot was already processed with higher sequence no need to process this sequence // THIS should never happen!! if (fixtureDelta.Sequence <= _lastSequenceProcessedInSnapshot) { _logger.WarnFormat("Stream update {0} will be ignored because snapshot with higher sequence={1} was already processed", fixtureDelta, _lastSequenceProcessedInSnapshot); return; } SuspendAndReprocessSnapshot(); return; } bool hasEpochChanged; var epochValid = IsEpochValid(fixtureDelta, out hasEpochChanged); if (epochValid) { ProcessSnapshot(fixtureDelta, false, hasEpochChanged); RaiseEvent(OnFinishedStreamUpdateProcessing); } else { _fixtureStartTime = fixtureDelta.StartTime; if (fixtureDelta.IsMatchStatusChanged && !string.IsNullOrEmpty(fixtureDelta.MatchStatus)) { _logger.DebugFormat("{0} has changed matchStatus={1}", _resource, Enum.Parse(typeof (MatchStatus), fixtureDelta.MatchStatus)); _platformConnector.ProcessMatchStatus(fixtureDelta); RaiseEvent(OnFinishedStreamUpdateProcessing); } bool stopStreaming = true; if ((fixtureDelta.IsMatchStatusChanged && fixtureDelta.IsMatchOver) || fixtureDelta.IsDeleted) { if (fixtureDelta.IsDeleted) { ProcessFixtureDelete(fixtureDelta); } else // Match Over { stopStreaming = ProcessMatchOver(fixtureDelta); } RaiseEvent(OnFinishedStreamUpdateProcessing); if (stopStreaming) Stop(); return; } _logger.InfoFormat("Stream update {0} will not be processed because epoch was not valid", fixtureDelta); SuspendAndReprocessSnapshot(hasEpochChanged); return; } _logger.InfoFormat("Update fo {0} processed successfully", fixtureDelta); } catch (AggregateException ex) { int total = ex.InnerExceptions.Count; int count = 0; foreach (var innerEx in ex.InnerExceptions) { _logger.ErrorFormat("Error processing update for {0} {1} ({2}/{3})",_resource, innerEx, ++count, total); } SetErrorState(); RaiseEvent(OnError, ex); } catch (Exception ex) { _logger.Error(string.Format("Error processing update {0}", _resource), ex); SetErrorState(); RaiseEvent(OnError, ex); } finally { ReleaseLock(); } }
private void GtpFixtureStreamEvent(object sender, StreamEventArgs e) { try { var resource = sender as IResource; //Notice the two-step deserialization var streamMessage = (StreamMessage)JsonConvert.DeserializeObject(e.Update, typeof(StreamMessage), new JsonSerializerSettings { Converters = new List<JsonConverter> { new IsoDateTimeConverter() }, NullValueHandling = NullValueHandling.Ignore }); var fixtureDelta = streamMessage.GetContent<Fixture>(); _logger.InfoFormat("Streaming Update arrived for {0} id {1} sequence {2}", _gtpFixture.Name, _gtpFixture.Id, fixtureDelta.Sequence); if (fixtureDelta.Sequence < _currentSequence) { _logger.InfoFormat("Fixture {0} id {1} sequence {2} is less than current sequence {3}", _gtpFixture.Name, _gtpFixture.Id, fixtureDelta.Sequence, _currentSequence); return; } if ((fixtureDelta.Sequence - _currentSequence) > 1) { _logger.WarnFormat("Fixture {0} id {1} sequence {2} is more than one greater that current sequence {3}", _gtpFixture.Name, _gtpFixture.Id, fixtureDelta.Sequence, _currentSequence); } _currentSequence = fixtureDelta.Sequence; //If the stream epoch does not equal the current epoch, //then we need to pause streaming, process the snapshot, carry on streaming if (fixtureDelta.Epoch > _currentEpoch) { _logger.InfoFormat("Epoch changed for {0} from {1} to {2}", _gtpFixture.Name, _currentEpoch, fixtureDelta.Epoch); _currentEpoch = fixtureDelta.Epoch; if (fixtureDelta.LastEpochChangeReason != null && fixtureDelta.LastEpochChangeReason.Contains((int)SSEpochChangeReason.StartTime)) { _logger.InfoFormat("Fixture {0} has had its start time changed", _gtpFixture.Name); ProcessDelta(fixtureDelta); } if (fixtureDelta.LastEpochChangeReason != null && fixtureDelta.LastEpochChangeReason.Contains((int)SSEpochChangeReason.Deleted)) { _logger.InfoFormat("Fixture {0} has been deleted from the GTP Fixture Factroy. Suspending all markets and stopping the stream", _gtpFixture.Name); _gtpFixture.StopStreaming(); SuspendAllMarkets(); FixtureEnded = true; } else { SuspendAndReprocessSnapshot(); } } else if (fixtureDelta.Epoch == _currentEpoch) { ProcessDelta(fixtureDelta); } } catch (Exception ex) { _logger.Error(ex); } }
public virtual void OnStreamEvent(StreamEventArgs e) { if (StreamEvent != null) StreamEvent(this, e); }