listener.rs

Overview

This file implements a key-based event listener system that allows clients to subscribe to changes on keys with specific prefixes. When a key change event occurs, all listeners registered for matching prefixes are notified with a stripped version of the event key. The main entities are Listeners, which manages multiple listeners efficiently, and ListenerHandle, which controls the lifecycle of individual subscriptions.

The system is optimized for relatively few listeners, using a nested map keyed by string prefixes and listener IDs. It supports automatic removal of listeners when their handles are dropped, with an option to keep listeners alive indefinitely via the forever method.

Key Concepts and Structures

ListenerHandle

A handle representing a subscription to a key prefix event. It manages the lifecycle of the listener:

Usage Example:

let handle = listeners.subscribe_event("prefix:", callback);
// Listener is automatically removed when `handle` is dropped,
// unless `handle.forever()` is called.

Listeners

A thread-safe, cloneable container managing multiple listeners:

Usage Example:

let listeners = Listeners::default();
let handle = listeners.subscribe_event("my_prefix:", |event| {
    println!("Received event: {:?}", event);
});
listeners.trigger_event(some_key_change_event);

InnerListeners

The internal structure holding all listeners and their identifiers:

Implementation Note:
Although a trie would be more efficient for prefix matching, the current approach uses a BTreeMap due to expected small listener counts.


Types and Aliases


How This File Interacts With Other Parts of the System


Important Algorithms and Implementation Details

Listener Subscription and Removal

Event Triggering


Visual Diagram

classDiagram
class ListenerHandle {
+prefix: String
+listener_id: usize
+listeners: Weak<RwLock<InnerListeners>>
+forever()
<<drop>>
}
class Listeners {
+inner: Arc<RwLock<InnerListeners>>
+subscribe_event()
+trigger_event()
}
class InnerListeners {
+listeners: BTreeMap<String, HashMap<usize, BoxedListener>>
+listener_idx: AtomicUsize
+subscribe_event()
+trigger_event()
+remove_listener()
}
ListenerHandle --> InnerListeners : weak reference
Listeners --> InnerListeners : Arc reference
Listeners --> ListenerHandle : returns
InnerListeners "1" *-- "*" BoxedListener : stores

Tests Summary

The file contains comprehensive tests verifying:

These tests demonstrate correct integration and concurrency safety of the listener system.


References