-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathdoc.go
More file actions
89 lines (89 loc) · 3.11 KB
/
Copy pathdoc.go
File metadata and controls
89 lines (89 loc) · 3.11 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
// Package mocrelay implements a Nostr relay as a composable Go library.
//
// mocrelay provides a middleware-composable architecture for building Nostr relays.
// The core abstraction is the [Handler] interface, which processes a single WebSocket
// connection's lifetime. Handlers can be composed using [Middleware] to add features
// like authentication, rate limiting, and content filtering.
//
// # Architecture
//
// The key types form a layered architecture:
//
// - [Relay] serves HTTP/WebSocket and manages connection lifecycles
// - [Handler] processes messages for a single connection
// - [Middleware] wraps a Handler to add cross-cutting concerns
// - [Storage] persists and queries events
// - [Router] routes events between connected clients in real-time
//
// # Handlers
//
// mocrelay provides several built-in handlers:
//
// - [NewStorageHandler] wraps a [Storage] to handle EVENT and REQ messages
// - [NewRouterHandler] wraps a [Router] to route events between clients
// - [NewMergeHandler] runs multiple handlers in parallel and merges responses
// - [NewNopHandler] is a minimal handler for testing
//
// Most handlers can be implemented using [SimpleHandlerBase], which provides
// a simpler message-at-a-time interface instead of managing channels directly.
//
// # Middleware
//
// Middleware is built on the [SimpleMiddlewareBase] interface. Multiple middleware
// bases are composed into a single pipeline via [NewSimpleMiddleware]:
//
// handler := NewSimpleMiddleware(
// NewMaxSubscriptionsMiddlewareBase(20),
// NewMaxLimitMiddlewareBase(500, 100),
// NewKindDenylistMiddlewareBase([]int64{4, 1059}),
// )(innerHandler)
//
// Built-in middleware corresponds to NIP-11 limitation and retention fields,
// providing a declarative way to configure relay policies.
//
// # Storage
//
// The [Storage] interface uses Go iterators ([iter.Seq]) for streaming query results:
//
// events, errFn, closeFn := storage.Query(ctx, filters)
// defer closeFn()
// for event := range events {
// // process event
// }
// if err := errFn(); err != nil {
// // handle error
// }
//
// [InMemoryStorage] is provided for testing. For production use, see [PebbleStorage]
// which wraps a caller-owned CockroachDB Pebble LSM-tree [*pebble.DB].
// Full-text search (NIP-50) is available via [BleveIndex], which wraps a
// caller-owned [bleve.Index].
//
// # Typical usage
//
// A typical relay combines storage, routing, middleware, and metrics.
// The caller owns the underlying pebble.DB (and bleve.Index, if used),
// which keeps [pebble.DB.Metrics] and database lifecycle in the caller's
// hands:
//
// db, _ := pebble.Open("/path/to/db", nil)
// defer db.Close()
// storage := NewPebbleStorage(db, nil)
//
// router := NewRouter(nil)
// handler := NewMergeHandler(
// []Handler{
// NewStorageHandler(storage, nil),
// NewRouterHandler(router),
// },
// nil,
// )
//
// handler = NewSimpleMiddleware(
// NewMaxSubscriptionsMiddlewareBase(20),
// NewMaxLimitMiddlewareBase(500, 100),
// )(handler)
//
// relay := NewRelay(handler, nil)
// http.ListenAndServe(":7447", relay)
package mocrelay