mirror of
https://github.com/nbd-wtf/go-nostr.git
synced 2025-07-17 23:12:19 +02:00
context cancelation for relay connections and subscriptions.
This commit is contained in:
15
relay.go
15
relay.go
@ -43,9 +43,10 @@ type Relay struct {
|
|||||||
Connection *Connection
|
Connection *Connection
|
||||||
subscriptions s.MapOf[string, *Subscription]
|
subscriptions s.MapOf[string, *Subscription]
|
||||||
|
|
||||||
Challenges chan string // NIP-42 Challenges
|
Challenges chan string // NIP-42 Challenges
|
||||||
Notices chan string
|
Notices chan string
|
||||||
ConnectionError chan error
|
ConnectionError chan error
|
||||||
|
ConnectionContext context.Context // will be canceled when the connection closes
|
||||||
|
|
||||||
okCallbacks s.MapOf[string, func(bool)]
|
okCallbacks s.MapOf[string, func(bool)]
|
||||||
|
|
||||||
@ -72,7 +73,11 @@ func (r *Relay) String() string {
|
|||||||
// Once successfully connected, context expiration has no effect: call r.Close
|
// Once successfully connected, context expiration has no effect: call r.Close
|
||||||
// to close the connection.
|
// to close the connection.
|
||||||
func (r *Relay) Connect(ctx context.Context) error {
|
func (r *Relay) Connect(ctx context.Context) error {
|
||||||
|
ctx, cancel := context.WithCancel(ctx)
|
||||||
|
r.ConnectionContext = ctx
|
||||||
|
|
||||||
if r.URL == "" {
|
if r.URL == "" {
|
||||||
|
cancel()
|
||||||
return fmt.Errorf("invalid relay URL '%s'", r.URL)
|
return fmt.Errorf("invalid relay URL '%s'", r.URL)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,6 +90,7 @@ func (r *Relay) Connect(ctx context.Context) error {
|
|||||||
|
|
||||||
socket, _, err := websocket.DefaultDialer.DialContext(ctx, r.URL, r.RequestHeader)
|
socket, _, err := websocket.DefaultDialer.DialContext(ctx, r.URL, r.RequestHeader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
cancel()
|
||||||
return fmt.Errorf("error opening websocket to '%s': %w", r.URL, err)
|
return fmt.Errorf("error opening websocket to '%s': %w", r.URL, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -198,6 +204,8 @@ func (r *Relay) Connect(ctx context.Context) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cancel()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@ -360,7 +368,6 @@ func (r *Relay) PrepareSubscription() *Subscription {
|
|||||||
random := make([]byte, 7)
|
random := make([]byte, 7)
|
||||||
rand.Read(random)
|
rand.Read(random)
|
||||||
id := hex.EncodeToString(random)
|
id := hex.EncodeToString(random)
|
||||||
|
|
||||||
return r.prepareSubscription(id)
|
return r.prepareSubscription(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@ type Subscription struct {
|
|||||||
Filters Filters
|
Filters Filters
|
||||||
Events chan *Event
|
Events chan *Event
|
||||||
EndOfStoredEvents chan struct{}
|
EndOfStoredEvents chan struct{}
|
||||||
|
Context context.Context
|
||||||
|
|
||||||
stopped bool
|
stopped bool
|
||||||
emitEose sync.Once
|
emitEose sync.Once
|
||||||
@ -46,6 +47,9 @@ func (sub *Subscription) Sub(ctx context.Context, filters Filters) {
|
|||||||
// Fire sends the "REQ" command to the relay.
|
// Fire sends the "REQ" command to the relay.
|
||||||
// When ctx is cancelled, sub.Unsub() is called, closing the subscription.
|
// When ctx is cancelled, sub.Unsub() is called, closing the subscription.
|
||||||
func (sub *Subscription) Fire(ctx context.Context) {
|
func (sub *Subscription) Fire(ctx context.Context) {
|
||||||
|
ctx, cancel := context.WithCancel(ctx)
|
||||||
|
sub.Context = ctx
|
||||||
|
|
||||||
message := []interface{}{"REQ", sub.id}
|
message := []interface{}{"REQ", sub.id}
|
||||||
for _, filter := range sub.Filters {
|
for _, filter := range sub.Filters {
|
||||||
message = append(message, filter)
|
message = append(message, filter)
|
||||||
@ -58,4 +62,16 @@ func (sub *Subscription) Fire(ctx context.Context) {
|
|||||||
<-ctx.Done()
|
<-ctx.Done()
|
||||||
sub.Unsub()
|
sub.Unsub()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
// or when the relay connection is closed
|
||||||
|
go func() {
|
||||||
|
<-sub.Relay.ConnectionContext.Done()
|
||||||
|
|
||||||
|
// this will close the Events channel,
|
||||||
|
// which can be used by an external reader to learn the subscription has stopped
|
||||||
|
sub.Unsub()
|
||||||
|
|
||||||
|
// we also cancel the context
|
||||||
|
cancel()
|
||||||
|
}()
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user