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 ProcessInvalidEpoch(Fixture fixtureDelta, bool hasEpochChanged)
        {
            _fixtureStartTime = fixtureDelta.StartTime ?? _fixtureStartTime;

            if (fixtureDelta.IsDeleted)
            {
                ProcessFixtureDelete(fixtureDelta);
                UpdateSupervisorState(fixtureDelta, false);
                StopStreaming();
                return;
            }

            if (fixtureDelta.IsMatchStatusChanged)
            {
                if (!string.IsNullOrEmpty(fixtureDelta.MatchStatus))
                {
                    _logger.Debug(
                        $"{_resource} has changed matchStatus={Enum.Parse(typeof(MatchStatus), fixtureDelta.MatchStatus)}");

                    try
                    {
                        _streamStatsActor.Tell(new UpdatePluginStatsStartMsg()
                        {
                            Fixture          = fixtureDelta,
                            Sequence         = fixtureDelta.Sequence,
                            IsSnapshot       = false,
                            UpdateReceivedAt = DateTime.UtcNow,
                            PluginMethod     = "ProcessMatchStatus"
                        });
                        _platformConnector.ProcessMatchStatus(fixtureDelta);
                        _streamStatsActor.Tell(new UpdatePluginStatsFinishMsg
                        {
                            CompletedAt = DateTime.UtcNow
                        });
                    }
                    catch (Exception ex)
                    {
                        var pluginError = new PluginException($"Plugin ProcessMatchStatus {fixtureDelta} error occured", ex);
                        UpdateStatsError(pluginError);
                        throw pluginError;
                    }
                }

                if (fixtureDelta.IsMatchOver)
                {
                    ProcessMatchOver();
                    StopStreaming();
                    return;
                }
            }

            //epoch change reason - aggregates LastEpochChange reasons into string like "BaseVariables,Starttime"
            var reason =
                fixtureDelta.LastEpochChangeReason != null && fixtureDelta.LastEpochChangeReason.Length > 0
                    ? fixtureDelta.LastEpochChangeReason.Select(x => ((EpochChangeReason)x).ToString())
                .Aggregate((first, second) => $"{first}, {second}")
                    : "Unknown";

            _logger.Info(
                $"Stream update {fixtureDelta} has epoch change with reason {reason}, the snapshot will be processed instead.");

            SuspendAndReprocessSnapshot(hasEpochChanged);
        }