-
Notifications
You must be signed in to change notification settings - Fork 4
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
Schedule.every Doesn't compensate for time spent executing block #13
Comments
@HCLarsen I'm actually aware of this limitation, it's not the way I intended it to run and I never had to concern about this difference in my use cases. I agree that this has to be fixed, but I'm afraid that the runner has to be reworked. |
You may not have to rework the entire runner. I tried writing a library like this myself before I realized that others had beat me to it. I was able to overcome the limitation(mostly) by calculating the delay from the time the iteration of the loop began. For instance:
WIth |
@HCLarsen but this solution may cause desynchronization if the |
@hugoabonizio are you talking about running every |
@HCLarsen something like that, but it's still required to catch the exceptions (inclusing the |
I look forward to seeing it. |
Looking at the code, it's basically taking the interval and passing it to a def self.every(interval, &block)
spawn do
loop do
sleep interval
run(block)
end
end
end
def self.every(interval : Symbol, &block)
spawn do
loop do
sleep calculate_interval(interval)
run(block)
end
end
end
def self.every(interval : Symbol, at : String | Array, &block)
spawn do
loop do
sleep calculate_interval(interval, at)
run(block)
end
end
end Before anything else I suggest refactoring this into: def self.every(interval, &block)
spawn do
loop do
sleep interval
run(block)
end
end
end
def self.every(interval : Symbol, &block)
every(calculate_interval(interval), block)
end
def self.every(interval : Symbol, at : String | Array, &block)
every(calculate_interval(interval, at), block)
end Now that the def self.every(interval, &block)
spawn do
loop do
duration = Time.measure do
run(block)
end
sleep interval - duration.total_seconds
end
end
end I'd probably shorten it to: def self.every(interval, &block)
spawn do
loop do
sleep interval - Time.measure{ run(block) }.total_seconds
end
end
end But then again, I'd also change the whole def self.every(interval, &block)
spawn { loop { sleep interval - Time.measure{ run(block) }.total_seconds } }
end which, let's face it, is overdoing it. Maybe a good compromise could be: def self.every(interval, &block)
spawn { loop do
sleep interval - Time.measure{ run(block) }.total_seconds
end }
end or: def self.spawnLoop(&block)
spawn { loop { yield } }
end
def self.every(interval, &block)
spawnLoop do
sleep interval - Time.measure{ run(block) }.total_seconds
end
end Anyways, In my case using a shard for this would be overkill (I wrote a pretty basic script to monitor some stuff, it only uses about 5Mb of RAM, so yeah, zero dependencies makes a lot of sense in my case), but maybe this can help others. |
I'm not sure if this is intended behaviour or not, but Schedule.every doesn't compensate for the time it takes to execute the block. For instance, if you have a block that takes 2 milliseconds to run, and you set the interval to 1 second, it doesn't run every second, it runs every 1.002 seconds. This can add up after a couple hundred iterations, meaning the time of your execution is inconsistent. Is this the way you intended it to run?
The text was updated successfully, but these errors were encountered: