Modules: Improve timer accuracy (#7987)
The bug occurs when 'callback' re-registers itself to a point in the future and the execution time in non-negligible: 'now' refers to time BEFORE callback was executed and is used to calculate 'next_period'. We must get the actual current time when calculating 'next_period'
This commit is contained in:
parent
b5f3996250
commit
1a91a2700b
16
src/module.c
16
src/module.c
@ -5442,7 +5442,10 @@ int moduleTimerHandler(struct aeEventLoop *eventLoop, long long id, void *client
|
|||||||
raxRemove(Timers,(unsigned char*)ri.key,ri.key_len,NULL);
|
raxRemove(Timers,(unsigned char*)ri.key,ri.key_len,NULL);
|
||||||
zfree(timer);
|
zfree(timer);
|
||||||
} else {
|
} else {
|
||||||
next_period = (expiretime-now)/1000; /* Scale to milliseconds. */
|
/* We call ustime() again instead of using the cached 'now' so that
|
||||||
|
* 'next_period' isn't affected by the time it took to execute
|
||||||
|
* previous calls to 'callback. */
|
||||||
|
next_period = (expiretime-ustime())/1000; /* Scale to milliseconds. */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -5455,7 +5458,16 @@ int moduleTimerHandler(struct aeEventLoop *eventLoop, long long id, void *client
|
|||||||
|
|
||||||
/* Create a new timer that will fire after `period` milliseconds, and will call
|
/* Create a new timer that will fire after `period` milliseconds, and will call
|
||||||
* the specified function using `data` as argument. The returned timer ID can be
|
* the specified function using `data` as argument. The returned timer ID can be
|
||||||
* used to get information from the timer or to stop it before it fires. */
|
* used to get information from the timer or to stop it before it fires.
|
||||||
|
* Note that for the common use case of a repeating timer (Re-registration
|
||||||
|
* of the timer inside the RedisModuleTimerProc callback) it matters when
|
||||||
|
* this API is called:
|
||||||
|
* If it is called at the beginning of 'callback' it means
|
||||||
|
* the event will triggered every 'period'.
|
||||||
|
* If it is called at the end of 'callback' it means
|
||||||
|
* there will 'period' milliseconds gaps between events.
|
||||||
|
* (If the time it takes to execute 'callback' is negligible the two
|
||||||
|
* statements above mean the same) */
|
||||||
RedisModuleTimerID RM_CreateTimer(RedisModuleCtx *ctx, mstime_t period, RedisModuleTimerProc callback, void *data) {
|
RedisModuleTimerID RM_CreateTimer(RedisModuleCtx *ctx, mstime_t period, RedisModuleTimerProc callback, void *data) {
|
||||||
RedisModuleTimer *timer = zmalloc(sizeof(*timer));
|
RedisModuleTimer *timer = zmalloc(sizeof(*timer));
|
||||||
timer->module = ctx->module;
|
timer->module = ctx->module;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user