108 lines
4.1 KiB
Markdown
108 lines
4.1 KiB
Markdown
# TASK METADATA
|
|
|
|
- **Target Files:** `sdk/mod.ts`, `sdk/mod.test.ts`
|
|
- **Core Objective:** Extend `@auth-yes/sdk` with a zero-dependency real-time
|
|
event bus to listen for Valkey 8 RESP3 push invalidation events and emit them
|
|
to registered listeners.
|
|
- **Dependencies:** None.
|
|
- **Additional Important Notes:** Handlers must support async execution. Errors
|
|
thrown by handlers must be caught and logged so they do not crash the Valkey
|
|
push listener or stop other registered handlers. No external EventEmitter
|
|
libraries are allowed.
|
|
|
|
---
|
|
|
|
## Architectural Considerations & Risks
|
|
|
|
### Risks
|
|
|
|
- **Memory Leaks:** Downstream consumers registering listeners for
|
|
`"invalidate"` without subsequently calling `off` could result in an unbounded
|
|
map of listeners. We must clearly document the `off` method and emphasize its
|
|
usage during cleanup (e.g., when a consumer class is destroyed or a connection
|
|
pool closes).
|
|
- **Callback Crash Propagation:** If a downstream consumer's callback throws an
|
|
exception (e.g., failing to terminate a WebSocket), and it is not caught, it
|
|
could crash the internal Valkey `push` event handler. The implementation must
|
|
guarantee isolated execution via a `try/catch` wrapper and gracefully handle
|
|
Promise rejections.
|
|
- **Payload Alignment:** Any discrepancy between the raw key emitted by Valkey
|
|
and the expected token by downstream listeners could result in missed
|
|
invalidations. As confirmed, Valkey stores and emits the raw `token` without
|
|
prefixes, so we must emit the token strictly as received.
|
|
|
|
### Alternatives
|
|
|
|
- Using the web standard `EventTarget` natively supported in Deno. While native,
|
|
standard `EventTarget` limits the payload to custom `Event` objects
|
|
(`CustomEvent`), which adds boilerplate (`event.detail.token`) and
|
|
type-casting complexity for downstream users. A custom lightweight callback
|
|
Set (`Set<InvalidationHandler>`) allows us to pass the `token: string` payload
|
|
directly and cleanly.
|
|
- Using an external EventEmitter package. This was rejected per the
|
|
zero-dependency directive.
|
|
|
|
## Proposed Implementation
|
|
|
|
### 1. Define the Handler Type
|
|
|
|
In `sdk/mod.ts`, define the TypeScript type for the invalidation handler:
|
|
|
|
```typescript
|
|
export type InvalidationHandler = (token: string) => void | Promise<void>;
|
|
```
|
|
|
|
### 2. Implement the Internal Event Bus
|
|
|
|
In the `AuthSdk` class (`sdk/mod.ts`):
|
|
|
|
- Add a private property to store listeners:
|
|
```typescript
|
|
private listeners: Map<string, Set<InvalidationHandler>> = new Map();
|
|
```
|
|
- Implement the `on` method:
|
|
```typescript
|
|
/**
|
|
* Registers a callback to be invoked when a specific event occurs.
|
|
* Currently, only the "invalidate" event is supported.
|
|
*
|
|
* @param event The event name (e.g., "invalidate").
|
|
* @param handler The callback function.
|
|
*/
|
|
on(event: "invalidate", handler: InvalidationHandler): void;
|
|
```
|
|
- Implement the `off` method:
|
|
```typescript
|
|
/**
|
|
* Unregisters a previously registered callback.
|
|
*
|
|
* @param event The event name (e.g., "invalidate").
|
|
* @param handler The callback function to remove.
|
|
*/
|
|
off(event: "invalidate", handler: InvalidationHandler): void;
|
|
```
|
|
|
|
### 3. Integrate with Valkey `push` Events
|
|
|
|
In the `initValkeyClient` method of `AuthSdk` (`sdk/mod.ts`):
|
|
|
|
- Locate the existing `"push"` event listener for the Valkey client.
|
|
- Inside the loop that iterates over `keysToInvalidate` (which represents the
|
|
raw tokens), add the emission logic.
|
|
- Retrieve the `Set` of listeners for the `"invalidate"` event.
|
|
- Iterate over the handlers and invoke them safely using a `try/catch` block and
|
|
`Promise.resolve(...).catch(...)` to prevent any single failing handler from
|
|
impacting the others or crashing the SDK.
|
|
|
|
### 4. Write Unit Tests
|
|
|
|
In `sdk/mod.test.ts`:
|
|
|
|
- Write tests to verify that `on` and `off` correctly add and remove handlers.
|
|
- Simulate the Valkey `"push"` event (e.g., by creating an instance with a
|
|
mocked `valkeyClient` or directly testing an internal emit method, or sending
|
|
mock payloads if the Valkey client is mocked).
|
|
- Verify that registered listeners are invoked with the correct token.
|
|
- Verify that a throwing or rejecting handler does not disrupt the execution of
|
|
subsequent handlers.
|