Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pastdue #195

Merged
merged 1 commit into from
Mar 7, 2017
Merged

Pastdue #195

merged 1 commit into from
Mar 7, 2017

Conversation

brettsam
Copy link
Member

Addressing #194.

The problem is that if the function has never run, we have no Last value to use for calculating Next when the host starts. So instead, we calculate from now. If the timer is past due, that means we'll miss it. Some customers have seen this happen when their site wakes up and restarts for one reason or another -- the timer doesn't get around to evaluating until a couple seconds after the scheduled execution. At that point, we recalculate the next execution and don't know that we've missed one.

This change adds a LastUpdated value to our serialized status. Even if the function has never run, we'll update LastUpdated to be the last time that we used when calculating Next. So when the host restarts, we have something to work with.

I've added tests to make sure that the 'legacy' behavior still works as expected -- since no one will have a LastUpdated value when this code starts running.

@brettsam
Copy link
Member Author

brettsam commented Mar 1, 2017

Also now addresses Azure/azure-functions-host#1246.

Copy link
Contributor

@mamaso mamaso left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, good tests :)

Couldn't find any obvious flaws in the logic

// Track the time that was used to create 'expectedNextOccurrence'.
DateTime lastUpdated;

if (lastStatus.LastUpdated != default(DateTime))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: could collapse this whole if else to something like:

DateTime lastUpdated = lastStatus?.LastUpdated ?? lastStatus?.Last ?? now;
expectedNextOccurrence = schedule.GetNextOccurrence(lastUpdated);

I like the comments, def helps the grok.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree -- but this is really confusing when you come back to it several months later (like always happens :-)), so I wanted to make sure the code and comments were verbose enough to be understood.

// if the schedule has changed and the next occurrence is in the past,
// recalculate it based on the current time as we don't want it to register
// immediately as 'past due'.
if (now > expectedNextOccurrence)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to be clear, we are treating 'now' as if it is the exact moment of schedule change, correct?

nit: Maybe we could route this via a function call to consolidate this to a invalid/no last status codepath, as this moment basically says 'throw out everything we know and start over'.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May want to change CheckPastDueAsync comments above to make sure they're consistent with this new delay behavior

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, think of LastUpdated as "the time we used when we last calculated Next". It's real value is allowing you to look at the current schedule and recalculate 'Next' to see if it has changed. We don't trust 'Next' unless we recalculate it ourselves on startup with the current schedule.

Does that make sense? I know it can get confusing -- hence the verbose comments :-)

}
else
else if (lastStatus.Last != default(DateTime))
Copy link
Member

@mathewc mathewc Mar 7, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't use of Last if present take precedence over use of the new LastUpdated? It seems we should calculate next using Last, LastUpdate, Now, in that order.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If LastUpdated exists, it will always be the same as Last. I'll look and see if I can easily swap them around and still have it be readable (I think I can).

Copy link
Member

@mathewc mathewc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had one comment , otherwise looks good

@mathewc
Copy link
Member

mathewc commented Mar 7, 2017

Shipit

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants