Skip to main content

valkey_module/context/
server_events.rs

1use std::ffi::CStr;
2
3use crate::{context::Context, ValkeyError};
4use crate::{raw, InfoContext, ValkeyResult};
5use linkme::distributed_slice;
6
7#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Debug)]
8pub enum ServerRole {
9    Primary,
10    Replica,
11}
12
13#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Debug)]
14pub enum LoadingSubevent {
15    RdbStarted,
16    AofStarted,
17    ReplStarted,
18    Ended,
19    Failed,
20}
21
22#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Debug)]
23pub enum FlushSubevent {
24    Started,
25    Ended,
26}
27
28#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Debug)]
29pub enum ModuleChangeSubevent {
30    Loaded,
31    Unloaded,
32}
33
34#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Debug)]
35pub enum ClientChangeSubevent {
36    Connected,
37    Disconnected,
38}
39
40#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Debug)]
41pub enum KeyChangeSubevent {
42    Deleted,
43    Expired,
44    Evicted,
45    Overwritten,
46}
47
48#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Debug)]
49pub enum PersistenceSubevent {
50    RdbStart,
51    AofStart,
52    SyncRdbStart,
53    SyncAofStart,
54    Ended,
55    Failed,
56}
57
58#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Debug)]
59pub enum MasterLinkChangeSubevent {
60    Up,
61    Down,
62}
63
64#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Debug)]
65pub enum ForkChildSubevent {
66    Born,
67    Died,
68}
69
70#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Debug)]
71pub enum ReplicaChangeSubevent {
72    Online,
73    Offline,
74}
75
76#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Debug)]
77pub enum ReplAsyncLoadSubevent {
78    Started,
79    Aborted,
80    Completed,
81}
82
83#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Debug)]
84pub enum LoadingProgressSubevent {
85    Rdb,
86    Aof,
87}
88
89#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Debug)]
90pub enum EventLoopSubevent {
91    BeforeSleep,
92    AfterSleep,
93}
94
95#[derive(Clone, Copy, Debug)]
96pub struct LoadingProgress {
97    pub subevent: LoadingProgressSubevent,
98    pub hz: i32,
99    pub progress: i32,
100}
101
102#[derive(Clone)]
103pub enum ServerEventHandler {
104    RoleChanged(fn(&Context, ServerRole)),
105    Loading(fn(&Context, LoadingSubevent)),
106    Flush(fn(&Context, FlushSubevent)),
107    ModuleChange(fn(&Context, ModuleChangeSubevent)),
108    ClientChange(fn(&Context, ClientChangeSubevent)),
109    KeyChangeSubevent(fn(&Context, KeyChangeSubevent)),
110    PersistenceSubevent(fn(&Context, PersistenceSubevent)),
111    MasterLinkChangeSubevent(fn(&Context, MasterLinkChangeSubevent)),
112    ForkChildSubevent(fn(&Context, ForkChildSubevent)),
113    ReplicaChangeSubevent(fn(&Context, ReplicaChangeSubevent)),
114    ReplAsyncLoadSubevent(fn(&Context, ReplAsyncLoadSubevent)),
115    LoadingProgress(fn(&Context, LoadingProgress)),
116    EventLoop(fn(&Context, EventLoopSubevent)),
117}
118
119#[distributed_slice()]
120pub static ROLE_CHANGED_SERVER_EVENTS_LIST: [fn(&Context, ServerRole)] = [..];
121
122#[distributed_slice()]
123pub static LOADING_SERVER_EVENTS_LIST: [fn(&Context, LoadingSubevent)] = [..];
124
125#[distributed_slice()]
126pub static FLUSH_SERVER_EVENTS_LIST: [fn(&Context, FlushSubevent)] = [..];
127
128#[distributed_slice()]
129pub static MODULE_CHANGED_SERVER_EVENTS_LIST: [fn(&Context, ModuleChangeSubevent)] = [..];
130
131#[distributed_slice()]
132pub static CONFIG_CHANGED_SERVER_EVENTS_LIST: [fn(&Context, &[&str])] = [..];
133
134#[distributed_slice()]
135pub static CRON_SERVER_EVENTS_LIST: [fn(&Context, u64)] = [..];
136
137#[distributed_slice()]
138pub static INFO_COMMAND_HANDLER_LIST: [fn(&InfoContext, bool) -> ValkeyResult<()>] = [..];
139
140#[distributed_slice()]
141pub static CLIENT_CHANGED_SERVER_EVENTS_LIST: [fn(&Context, ClientChangeSubevent)] = [..];
142
143#[distributed_slice()]
144pub static KEY_SERVER_EVENTS_LIST: [fn(&Context, KeyChangeSubevent)] = [..];
145
146#[distributed_slice()]
147pub static SHUTDOWN_SERVER_EVENT_LIST: [fn(&Context, u64)] = [..];
148
149#[distributed_slice()]
150pub static PERSISTENCE_SERVER_EVENTS_LIST: [fn(&Context, PersistenceSubevent)] = [..];
151
152#[distributed_slice()]
153pub static MASTER_LINK_CHANGE_SERVER_EVENTS_LIST: [fn(&Context, MasterLinkChangeSubevent)] = [..];
154
155#[distributed_slice()]
156pub static FORK_CHILD_SERVER_EVENTS_LIST: [fn(&Context, ForkChildSubevent)] = [..];
157
158#[distributed_slice()]
159pub static REPLICA_CHANGE_SERVER_EVENTS_LIST: [fn(&Context, ReplicaChangeSubevent)] = [..];
160
161#[distributed_slice()]
162pub static REPL_ASYNC_LOAD_SERVER_EVENTS_LIST: [fn(&Context, ReplAsyncLoadSubevent)] = [..];
163
164#[distributed_slice()]
165pub static SWAPDB_SERVER_EVENTS_LIST: [fn(&Context, u64)] = [..];
166
167#[distributed_slice()]
168pub static LOADING_PROGRESS_SERVER_EVENTS_LIST: [fn(&Context, LoadingProgress)] = [..];
169
170#[distributed_slice()]
171pub static EVENT_LOOP_SERVER_EVENTS_LIST: [fn(&Context, EventLoopSubevent)] = [..];
172
173extern "C" fn cron_callback(
174    ctx: *mut raw::RedisModuleCtx,
175    _eid: raw::RedisModuleEvent,
176    _subevent: u64,
177    data: *mut ::std::os::raw::c_void,
178) {
179    let data: &raw::RedisModuleConfigChangeV1 =
180        unsafe { &*(data as *mut raw::RedisModuleConfigChangeV1) };
181    let ctx = Context::new(ctx);
182    CRON_SERVER_EVENTS_LIST.iter().for_each(|callback| {
183        callback(&ctx, data.version);
184    });
185}
186
187extern "C" fn role_changed_callback(
188    ctx: *mut raw::RedisModuleCtx,
189    _eid: raw::RedisModuleEvent,
190    subevent: u64,
191    _data: *mut ::std::os::raw::c_void,
192) {
193    let new_role = if subevent == raw::REDISMODULE_EVENT_REPLROLECHANGED_NOW_MASTER {
194        ServerRole::Primary
195    } else {
196        ServerRole::Replica
197    };
198    let ctx = Context::new(ctx);
199    ROLE_CHANGED_SERVER_EVENTS_LIST.iter().for_each(|callback| {
200        callback(&ctx, new_role);
201    });
202}
203
204extern "C" fn loading_event_callback(
205    ctx: *mut raw::RedisModuleCtx,
206    _eid: raw::RedisModuleEvent,
207    subevent: u64,
208    _data: *mut ::std::os::raw::c_void,
209) {
210    let loading_sub_event = match subevent {
211        raw::REDISMODULE_SUBEVENT_LOADING_RDB_START => LoadingSubevent::RdbStarted,
212        raw::REDISMODULE_SUBEVENT_LOADING_REPL_START => LoadingSubevent::ReplStarted,
213        raw::REDISMODULE_SUBEVENT_LOADING_AOF_START => LoadingSubevent::AofStarted,
214        raw::REDISMODULE_SUBEVENT_LOADING_ENDED => LoadingSubevent::Ended,
215        _ => LoadingSubevent::Failed,
216    };
217    let ctx = Context::new(ctx);
218    LOADING_SERVER_EVENTS_LIST.iter().for_each(|callback| {
219        callback(&ctx, loading_sub_event);
220    });
221}
222
223extern "C" fn flush_event_callback(
224    ctx: *mut raw::RedisModuleCtx,
225    _eid: raw::RedisModuleEvent,
226    subevent: u64,
227    _data: *mut ::std::os::raw::c_void,
228) {
229    let flush_sub_event = if subevent == raw::REDISMODULE_SUBEVENT_FLUSHDB_START {
230        FlushSubevent::Started
231    } else {
232        FlushSubevent::Ended
233    };
234    let ctx = Context::new(ctx);
235    FLUSH_SERVER_EVENTS_LIST.iter().for_each(|callback| {
236        callback(&ctx, flush_sub_event);
237    });
238}
239
240extern "C" fn module_change_event_callback(
241    ctx: *mut raw::RedisModuleCtx,
242    _eid: raw::RedisModuleEvent,
243    subevent: u64,
244    _data: *mut ::std::os::raw::c_void,
245) {
246    let module_changed_sub_event = if subevent == raw::REDISMODULE_SUBEVENT_MODULE_LOADED {
247        ModuleChangeSubevent::Loaded
248    } else {
249        ModuleChangeSubevent::Unloaded
250    };
251    let ctx = Context::new(ctx);
252    MODULE_CHANGED_SERVER_EVENTS_LIST
253        .iter()
254        .for_each(|callback| {
255            callback(&ctx, module_changed_sub_event);
256        });
257}
258
259extern "C" fn client_change_event_callback(
260    ctx: *mut raw::RedisModuleCtx,
261    _eid: raw::RedisModuleEvent,
262    subevent: u64,
263    _data: *mut ::std::os::raw::c_void,
264) {
265    let client_change_sub_event = if subevent == raw::REDISMODULE_SUBEVENT_CLIENT_CHANGE_CONNECTED {
266        ClientChangeSubevent::Connected
267    } else {
268        ClientChangeSubevent::Disconnected
269    };
270    let ctx = Context::new(ctx);
271    CLIENT_CHANGED_SERVER_EVENTS_LIST
272        .iter()
273        .for_each(|callback| {
274            callback(&ctx, client_change_sub_event);
275        });
276}
277
278extern "C" fn key_event_callback(
279    ctx: *mut raw::RedisModuleCtx,
280    _eid: raw::RedisModuleEvent,
281    subevent: u64,
282    _data: *mut ::std::os::raw::c_void,
283) {
284    let key_change_sub_event = match subevent {
285        raw::REDISMODULE_SUBEVENT_KEY_DELETED => KeyChangeSubevent::Deleted,
286        raw::REDISMODULE_SUBEVENT_KEY_EXPIRED => KeyChangeSubevent::Expired,
287        raw::REDISMODULE_SUBEVENT_KEY_EVICTED => KeyChangeSubevent::Evicted,
288        raw::REDISMODULE_SUBEVENT_KEY_OVERWRITTEN => KeyChangeSubevent::Overwritten,
289        _ => return,
290    };
291    let ctx = Context::new(ctx);
292    KEY_SERVER_EVENTS_LIST.iter().for_each(|callback| {
293        callback(&ctx, key_change_sub_event);
294    });
295}
296
297extern "C" fn server_shutdown_callback(
298    ctx: *mut raw::RedisModuleCtx,
299    _eid: raw::RedisModuleEvent,
300    subevent: u64,
301    _data: *mut ::std::os::raw::c_void,
302) {
303    let ctx = Context::new(ctx);
304    SHUTDOWN_SERVER_EVENT_LIST.iter().for_each(|callback| {
305        callback(&ctx, subevent);
306    });
307}
308
309extern "C" fn persistence_event_callback(
310    ctx: *mut raw::RedisModuleCtx,
311    _eid: raw::RedisModuleEvent,
312    subevent: u64,
313    _data: *mut ::std::os::raw::c_void,
314) {
315    let persistence_sub_event = match subevent {
316        raw::REDISMODULE_SUBEVENT_PERSISTENCE_RDB_START => PersistenceSubevent::RdbStart,
317        raw::REDISMODULE_SUBEVENT_PERSISTENCE_AOF_START => PersistenceSubevent::AofStart,
318        raw::REDISMODULE_SUBEVENT_PERSISTENCE_SYNC_RDB_START => PersistenceSubevent::SyncRdbStart,
319        raw::REDISMODULE_SUBEVENT_PERSISTENCE_SYNC_AOF_START => PersistenceSubevent::SyncAofStart,
320        raw::REDISMODULE_SUBEVENT_PERSISTENCE_ENDED => PersistenceSubevent::Ended,
321        raw::REDISMODULE_SUBEVENT_PERSISTENCE_FAILED => PersistenceSubevent::Failed,
322        _ => return,
323    };
324    let ctx = Context::new(ctx);
325    PERSISTENCE_SERVER_EVENTS_LIST.iter().for_each(|callback| {
326        callback(&ctx, persistence_sub_event);
327    });
328}
329
330extern "C" fn master_link_change_event_callback(
331    ctx: *mut raw::RedisModuleCtx,
332    _eid: raw::RedisModuleEvent,
333    subevent: u64,
334    _data: *mut ::std::os::raw::c_void,
335) {
336    let master_link_change_sub_event = match subevent {
337        raw::REDISMODULE_SUBEVENT_MASTER_LINK_UP => MasterLinkChangeSubevent::Up,
338        raw::REDISMODULE_SUBEVENT_MASTER_LINK_DOWN => MasterLinkChangeSubevent::Down,
339        _ => return,
340    };
341    let ctx = Context::new(ctx);
342    MASTER_LINK_CHANGE_SERVER_EVENTS_LIST
343        .iter()
344        .for_each(|callback| {
345            callback(&ctx, master_link_change_sub_event);
346        });
347}
348
349extern "C" fn config_change_event_callback(
350    ctx: *mut raw::RedisModuleCtx,
351    _eid: raw::RedisModuleEvent,
352    _subevent: u64,
353    data: *mut ::std::os::raw::c_void,
354) {
355    let data: &raw::RedisModuleConfigChange =
356        unsafe { &*(data as *mut raw::RedisModuleConfigChange) };
357    let config_names: Vec<_> = (0..data.num_changes)
358        .map(|i| unsafe {
359            let name = *data.config_names.offset(i as isize);
360            CStr::from_ptr(name)
361        })
362        .collect();
363    let config_names: Vec<_> = config_names
364        .iter()
365        .map(|v| {
366            v.to_str()
367                .expect("Got a configuration name which is not a valid utf8")
368        })
369        .collect();
370    let ctx = Context::new(ctx);
371    CONFIG_CHANGED_SERVER_EVENTS_LIST
372        .iter()
373        .for_each(|callback| {
374            callback(&ctx, config_names.as_slice());
375        });
376}
377
378extern "C" fn fork_child_event_callback(
379    ctx: *mut raw::RedisModuleCtx,
380    _eid: raw::RedisModuleEvent,
381    subevent: u64,
382    _data: *mut ::std::os::raw::c_void,
383) {
384    let fork_child_sub_event = match subevent {
385        raw::REDISMODULE_SUBEVENT_FORK_CHILD_BORN => ForkChildSubevent::Born,
386        raw::REDISMODULE_SUBEVENT_FORK_CHILD_DIED => ForkChildSubevent::Died,
387        _ => return,
388    };
389    let ctx = Context::new(ctx);
390    FORK_CHILD_SERVER_EVENTS_LIST.iter().for_each(|callback| {
391        callback(&ctx, fork_child_sub_event);
392    });
393}
394
395extern "C" fn replica_change_event_callback(
396    ctx: *mut raw::RedisModuleCtx,
397    _eid: raw::RedisModuleEvent,
398    subevent: u64,
399    _data: *mut ::std::os::raw::c_void,
400) {
401    let replica_change_sub_event = match subevent {
402        raw::REDISMODULE_SUBEVENT_REPLICA_CHANGE_ONLINE => ReplicaChangeSubevent::Online,
403        raw::REDISMODULE_SUBEVENT_REPLICA_CHANGE_OFFLINE => ReplicaChangeSubevent::Offline,
404        _ => return,
405    };
406    let ctx = Context::new(ctx);
407    REPLICA_CHANGE_SERVER_EVENTS_LIST
408        .iter()
409        .for_each(|callback| {
410            callback(&ctx, replica_change_sub_event);
411        });
412}
413
414extern "C" fn repl_async_load_event_callback(
415    ctx: *mut raw::RedisModuleCtx,
416    _eid: raw::RedisModuleEvent,
417    subevent: u64,
418    _data: *mut ::std::os::raw::c_void,
419) {
420    let repl_async_load_sub_event = match subevent {
421        raw::REDISMODULE_SUBEVENT_REPL_ASYNC_LOAD_STARTED => ReplAsyncLoadSubevent::Started,
422        raw::REDISMODULE_SUBEVENT_REPL_ASYNC_LOAD_ABORTED => ReplAsyncLoadSubevent::Aborted,
423        raw::REDISMODULE_SUBEVENT_REPL_ASYNC_LOAD_COMPLETED => ReplAsyncLoadSubevent::Completed,
424        _ => return,
425    };
426    let ctx = Context::new(ctx);
427    REPL_ASYNC_LOAD_SERVER_EVENTS_LIST
428        .iter()
429        .for_each(|callback| {
430            callback(&ctx, repl_async_load_sub_event);
431        });
432}
433
434extern "C" fn swapdb_callback(
435    ctx: *mut raw::RedisModuleCtx,
436    _eid: raw::RedisModuleEvent,
437    subevent: u64,
438    _data: *mut ::std::os::raw::c_void,
439) {
440    let ctx = Context::new(ctx);
441    SWAPDB_SERVER_EVENTS_LIST.iter().for_each(|callback| {
442        callback(&ctx, subevent);
443    });
444}
445
446fn register_single_server_event_type<T>(
447    ctx: &Context,
448    callbacks: &[fn(&Context, T)],
449    server_event: u64,
450    inner_callback: raw::RedisModuleEventCallback,
451) -> Result<(), ValkeyError> {
452    if !callbacks.is_empty() {
453        let res = unsafe {
454            raw::RedisModule_SubscribeToServerEvent.unwrap()(
455                ctx.ctx,
456                raw::RedisModuleEvent {
457                    id: server_event,
458                    dataver: 1,
459                },
460                inner_callback,
461            )
462        };
463        if res != raw::REDISMODULE_OK as i32 {
464            return Err(ValkeyError::Str("Failed subscribing to server event"));
465        }
466    }
467
468    Ok(())
469}
470
471extern "C" fn loading_progress_event_callback(
472    ctx: *mut raw::RedisModuleCtx,
473    _eid: raw::RedisModuleEvent,
474    subevent: u64,
475    data: *mut ::std::os::raw::c_void,
476) {
477    if data.is_null() {
478        return;
479    }
480
481    // Cast to the generated raw binding for the loading progress struct
482    let info: &raw::RedisModuleLoadingProgressInfo =
483        unsafe { &*(data as *mut raw::RedisModuleLoadingProgressInfo) };
484
485    let hz = info.hz as i32;
486    let progress = info.progress as i32;
487
488    let sub = match subevent {
489        raw::REDISMODULE_SUBEVENT_LOADING_PROGRESS_RDB => LoadingProgressSubevent::Rdb,
490        raw::REDISMODULE_SUBEVENT_LOADING_PROGRESS_AOF => LoadingProgressSubevent::Aof,
491        _ => return,
492    };
493
494    let ctx = Context::new(ctx);
495    let payload = LoadingProgress {
496        subevent: sub,
497        hz,
498        progress,
499    };
500
501    LOADING_PROGRESS_SERVER_EVENTS_LIST
502        .iter()
503        .for_each(|callback| {
504            callback(&ctx, payload);
505        });
506}
507
508extern "C" fn event_loop_event_callback(
509    ctx: *mut raw::RedisModuleCtx,
510    _eid: raw::RedisModuleEvent,
511    subevent: u64,
512    _data: *mut ::std::os::raw::c_void,
513) {
514    let event_loop_subevent = match subevent {
515        raw::REDISMODULE_SUBEVENT_EVENTLOOP_BEFORE_SLEEP => EventLoopSubevent::BeforeSleep,
516        raw::REDISMODULE_SUBEVENT_EVENTLOOP_AFTER_SLEEP => EventLoopSubevent::AfterSleep,
517        _ => return,
518    };
519    let ctx = Context::new(ctx);
520    EVENT_LOOP_SERVER_EVENTS_LIST.iter().for_each(|callback| {
521        callback(&ctx, event_loop_subevent);
522    });
523}
524
525pub fn register_server_events(ctx: &Context) -> Result<(), ValkeyError> {
526    register_single_server_event_type(
527        ctx,
528        &ROLE_CHANGED_SERVER_EVENTS_LIST,
529        raw::REDISMODULE_EVENT_REPLICATION_ROLE_CHANGED,
530        Some(role_changed_callback),
531    )?;
532    register_single_server_event_type(
533        ctx,
534        &LOADING_SERVER_EVENTS_LIST,
535        raw::REDISMODULE_EVENT_LOADING,
536        Some(loading_event_callback),
537    )?;
538    register_single_server_event_type(
539        ctx,
540        &FLUSH_SERVER_EVENTS_LIST,
541        raw::REDISMODULE_EVENT_FLUSHDB,
542        Some(flush_event_callback),
543    )?;
544    register_single_server_event_type(
545        ctx,
546        &MODULE_CHANGED_SERVER_EVENTS_LIST,
547        raw::REDISMODULE_EVENT_MODULE_CHANGE,
548        Some(module_change_event_callback),
549    )?;
550    register_single_server_event_type(
551        ctx,
552        &CLIENT_CHANGED_SERVER_EVENTS_LIST,
553        raw::REDISMODULE_EVENT_CLIENT_CHANGE,
554        Some(client_change_event_callback),
555    )?;
556    register_single_server_event_type(
557        ctx,
558        &CONFIG_CHANGED_SERVER_EVENTS_LIST,
559        raw::REDISMODULE_EVENT_CONFIG,
560        Some(config_change_event_callback),
561    )?;
562    register_single_server_event_type(
563        ctx,
564        &CRON_SERVER_EVENTS_LIST,
565        raw::REDISMODULE_EVENT_CRON_LOOP,
566        Some(cron_callback),
567    )?;
568    register_single_server_event_type(
569        ctx,
570        &KEY_SERVER_EVENTS_LIST,
571        raw::REDISMODULE_EVENT_KEY,
572        Some(key_event_callback),
573    )?;
574    register_single_server_event_type(
575        ctx,
576        &SHUTDOWN_SERVER_EVENT_LIST,
577        raw::REDISMODULE_EVENT_SHUTDOWN,
578        Some(server_shutdown_callback),
579    )?;
580    register_single_server_event_type(
581        ctx,
582        &PERSISTENCE_SERVER_EVENTS_LIST,
583        raw::REDISMODULE_EVENT_PERSISTENCE,
584        Some(persistence_event_callback),
585    )?;
586    register_single_server_event_type(
587        ctx,
588        &MASTER_LINK_CHANGE_SERVER_EVENTS_LIST,
589        raw::REDISMODULE_EVENT_MASTER_LINK_CHANGE,
590        Some(master_link_change_event_callback),
591    )?;
592    register_single_server_event_type(
593        ctx,
594        &FORK_CHILD_SERVER_EVENTS_LIST,
595        raw::REDISMODULE_EVENT_FORK_CHILD,
596        Some(fork_child_event_callback),
597    )?;
598    register_single_server_event_type(
599        ctx,
600        &REPLICA_CHANGE_SERVER_EVENTS_LIST,
601        raw::REDISMODULE_EVENT_REPLICA_CHANGE,
602        Some(replica_change_event_callback),
603    )?;
604    register_single_server_event_type(
605        ctx,
606        &REPL_ASYNC_LOAD_SERVER_EVENTS_LIST,
607        raw::REDISMODULE_EVENT_REPL_ASYNC_LOAD,
608        Some(repl_async_load_event_callback),
609    )?;
610    register_single_server_event_type(
611        ctx,
612        &SWAPDB_SERVER_EVENTS_LIST,
613        raw::REDISMODULE_EVENT_SWAPDB,
614        Some(swapdb_callback),
615    )?;
616    register_single_server_event_type(
617        ctx,
618        &LOADING_PROGRESS_SERVER_EVENTS_LIST,
619        raw::REDISMODULE_EVENT_LOADING_PROGRESS,
620        Some(loading_progress_event_callback),
621    )?;
622    register_single_server_event_type(
623        ctx,
624        &EVENT_LOOP_SERVER_EVENTS_LIST,
625        raw::REDISMODULE_EVENT_EVENTLOOP,
626        Some(event_loop_event_callback),
627    )?;
628    Ok(())
629}