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 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}