private void CalculateProgressBeforeRead()
        {
            var start            = Progress?.NextIterationStart ?? _context.StartInstant;
            var endCutoffInstant = InstantUtils.SecondsAgo(_context.ClockSkewProtectionSeconds);
            var minEndInstant    = start.Plus(Duration.FromSeconds(_context.MinIntervalSeconds));
            var maxEndInstant    = start.Plus(Duration.FromSeconds(_context.MaxIntervalSeconds));

            var end = Progress?.NextIterationEnd ?? maxEndInstant;

            if (end > maxEndInstant)
            {
                end = maxEndInstant;
            }
            if (end > endCutoffInstant)
            {
                end = endCutoffInstant;
            }
            if (end < minEndInstant)
            {
                end = minEndInstant;
            }

            // Fix the iteration based on _context.End only if the _context.End is between progress start and end
            // (so that the iteration needs to be run partially). We don't need to consider any other cases, if
            // the Progress.end is passed _context.end, we won't run the iteration anyway.
            if (_context.EndInstant.HasValue &&
                start < _context.EndInstant.Value &&
                end > _context.EndInstant.Value)
            {
                end = _context.EndInstant.Value;
            }

            Progress = new JobProgress(start, end, Progress?.NextToken);
        }
        private JobProgress CalculateProgressAfterRead()
        {
            // There's no need to consider _context.End here. We just calculate the prospective next iteration span
            // and it will be looked at and fixed before the next iteration, if needed.

            if (!string.IsNullOrWhiteSpace(_readResponse.NextToken))
            {
                return(new JobProgress(Progress.NextIterationStart, Progress.NextIterationEnd, _readResponse.NextToken));
            }

            // If the current timespan is completed, we start from one millisecond after the end of this timespan
            // because AWS APIs accept milliseconds as timespan, so the resolution is 1 ms. And the API is
            // inclusive for both start and end, so we don't want events with timestamp equal to previous end
            // be returned twice.
            var start = Progress.NextIterationEnd.Plus(Duration.FromMilliseconds(1));

            var endCutoffInstant = InstantUtils.SecondsAgo(_context.ClockSkewProtectionSeconds);
            var minEndInstant    = start.Plus(Duration.FromSeconds(_context.MinIntervalSeconds));
            var maxEndInstant    = start.Plus(Duration.FromSeconds(_context.MaxIntervalSeconds));

            if (minEndInstant > endCutoffInstant)
            {
                return(new JobProgress(start, minEndInstant, null));
            }

            var end = maxEndInstant;

            if (end > endCutoffInstant)
            {
                end = endCutoffInstant;
            }

            return(new JobProgress(start, end, null));
        }
Beispiel #3
0
        private static Instant?ParseAbsoluteOrRelativeTime(string absoluteTime, int?relativeTimeSecondsAgo)
        {
            if (!string.IsNullOrWhiteSpace(absoluteTime))
            {
                var parsedTime = InstantPattern.Parse(absoluteTime);
                if (!parsedTime.Success)
                {
                    throw new ArgumentException($"Time pattern '{absoluteTime}' could not be parsed. ISO-8601 based UTC format without fractions of second is expected.");
                }

                return(parsedTime.Value);
            }

            if (relativeTimeSecondsAgo.HasValue)
            {
                return(InstantUtils.SecondsAgo(relativeTimeSecondsAgo.Value));
            }

            return(null);
        }
        private bool IsRunnable(JobProgress progress)
        {
            if (_context.EndInstant.HasValue)
            {
                // Just check for the end. If this would have been a partial iteration (_context.End was between
                // Progress.Start and Progress.End), CalculateProgressBeforeRead method would have been adjusted it.
                if (progress.NextIterationEnd > _context.EndInstant.Value)
                {
                    return(false);
                }

                // If the Progress.End is exactly equal to _context.End, allow it to be run without any regard
                // to cut-off, since it's the last iteration ever to be run.
                if (progress.NextIterationEnd == _context.EndInstant.Value)
                {
                    return(true);
                }
            }

            var endCutoffInstant = InstantUtils.SecondsAgo(_context.ClockSkewProtectionSeconds);

            return(progress.NextIterationEnd <= endCutoffInstant);
        }