nwc-ruby 0.2.2 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +13 -0
- data/README.md +8 -0
- data/lib/nwc_ruby/transport/relay_connection.rb +39 -3
- data/lib/nwc_ruby/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d541ad9af31629ad26492d8da61d56b0a63980cc8597a460cca9949df56f382d
|
|
4
|
+
data.tar.gz: 8d48fbbe532bdcf56d889f68f9d7878fa2958381c1ea285fb572aebb70d17d7e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: bbc5e4a3efdac9b24a4a2c5fc183f3945ba9987fd5312c78a7e8c4ba8cff625af5c08521094cc10101fd24a0bef5f35261eb29720d533d7e0167a236ee59d106
|
|
7
|
+
data.tar.gz: fb2c7a1ed8d7785a886b38e250432466354b257cef1e4c8552ef24c493c304dbd446bf4c17e57debcce8bc6875666686c16f901d29474ef08541194e6e2a97f3
|
data/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- Silenced the noisy `Async::Task` warn log ("Task may have ended with
|
|
13
|
+
unhandled exception") that was emitted every `recycle_interval` (default
|
|
14
|
+
5 min) by the heartbeat task. The forced recycle used to be signaled by
|
|
15
|
+
raising `TransportError` from inside the heartbeat's child Async task; the
|
|
16
|
+
parent's reconnect loop caught it correctly, but Async's console logger
|
|
17
|
+
logged the unhandled-in-child exception with a full backtrace first.
|
|
18
|
+
The recycle is now signaled by setting an `@recycle_requested` flag and
|
|
19
|
+
closing the websocket, which unblocks the read loop and lets
|
|
20
|
+
`run_one_connection` return normally without any exception crossing a task
|
|
21
|
+
boundary.
|
|
22
|
+
|
|
10
23
|
## [0.2.2] — 2026-04-21
|
|
11
24
|
|
|
12
25
|
### Fixed
|
data/README.md
CHANGED
|
@@ -2,6 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
A production-grade Ruby client for [Nostr Wallet Connect (NIP-47)][nip47].
|
|
4
4
|
|
|
5
|
+
Accept and track Bitcoin Lightning payments in your Rails app without running
|
|
6
|
+
any Lightning infrastructure yourself. Generate Lightning invoices for your
|
|
7
|
+
users to pay, then get notified the instant each one settles — all by talking
|
|
8
|
+
to a Nostr Wallet Connect (NWC) service that someone else operates. The gem
|
|
9
|
+
works with any NWC-compatible backend (Rizful, Alby Hub, Alby Cloud, CoinOs,
|
|
10
|
+
any NIP-47 wallet service), so you're not locked into a single provider and
|
|
11
|
+
can swap vendors by changing one environment variable.
|
|
12
|
+
|
|
5
13
|
```ruby
|
|
6
14
|
require "nwc_ruby"
|
|
7
15
|
|
|
@@ -146,6 +146,7 @@ module NwcRuby
|
|
|
146
146
|
def run_one_connection(top)
|
|
147
147
|
endpoint = Async::HTTP::Endpoint.parse(@url, alpn_protocols: ['http/1.1'])
|
|
148
148
|
opened_at = Async::Clock.now
|
|
149
|
+
@recycle_requested = false
|
|
149
150
|
@logger.info("[nwc] connecting to #{@url}")
|
|
150
151
|
|
|
151
152
|
Async::WebSocket::Client.connect(endpoint) do |conn|
|
|
@@ -155,6 +156,7 @@ module NwcRuby
|
|
|
155
156
|
|
|
156
157
|
@open_cb&.call(self)
|
|
157
158
|
read_loop(conn)
|
|
159
|
+
@logger.info("[nwc] recycling connection (#{@recycle_interval}s)") if @recycle_requested
|
|
158
160
|
ensure
|
|
159
161
|
heartbeat&.stop
|
|
160
162
|
poll&.stop
|
|
@@ -167,6 +169,13 @@ module NwcRuby
|
|
|
167
169
|
end
|
|
168
170
|
end
|
|
169
171
|
|
|
172
|
+
# Heartbeat task: sends RFC 6455 ping every @ping_interval seconds and
|
|
173
|
+
# requests a recycle once the connection has been open longer than
|
|
174
|
+
# @recycle_interval. The recycle is signaled via a flag + close rather
|
|
175
|
+
# than by raising across task boundaries, because an exception raised
|
|
176
|
+
# inside a child Async task is logged at warn level by Async's console
|
|
177
|
+
# logger ("Task may have ended with unhandled exception") before the
|
|
178
|
+
# parent's rescue runs — producing a noisy backtrace on every recycle.
|
|
170
179
|
def start_heartbeat(top, conn, opened_at)
|
|
171
180
|
top.async do
|
|
172
181
|
loop do
|
|
@@ -176,12 +185,25 @@ module NwcRuby
|
|
|
176
185
|
|
|
177
186
|
sleep @ping_interval
|
|
178
187
|
break if @stop
|
|
179
|
-
|
|
180
|
-
raise TransportError, "recycle (#{@recycle_interval}s)" if Async::Clock.now - opened_at > @recycle_interval
|
|
188
|
+
break if recycle_due?(opened_at) && request_recycle(conn)
|
|
181
189
|
end
|
|
182
190
|
end
|
|
183
191
|
end
|
|
184
192
|
|
|
193
|
+
def recycle_due?(opened_at)
|
|
194
|
+
Async::Clock.now - opened_at > @recycle_interval
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
def request_recycle(conn)
|
|
198
|
+
@recycle_requested = true
|
|
199
|
+
begin
|
|
200
|
+
conn.close
|
|
201
|
+
rescue StandardError
|
|
202
|
+
nil
|
|
203
|
+
end
|
|
204
|
+
true
|
|
205
|
+
end
|
|
206
|
+
|
|
185
207
|
def start_poll(top)
|
|
186
208
|
return unless @poll_interval && @poll_cb
|
|
187
209
|
|
|
@@ -200,7 +222,21 @@ module NwcRuby
|
|
|
200
222
|
end
|
|
201
223
|
|
|
202
224
|
def read_loop(conn)
|
|
203
|
-
|
|
225
|
+
loop do
|
|
226
|
+
message =
|
|
227
|
+
begin
|
|
228
|
+
conn.read
|
|
229
|
+
rescue StandardError => e
|
|
230
|
+
# If we asked for the recycle/close ourselves, treat the
|
|
231
|
+
# resulting read error as a clean EOF rather than propagating
|
|
232
|
+
# it up into the reconnect-on-error path (which would log a
|
|
233
|
+
# spurious warning).
|
|
234
|
+
raise unless @recycle_requested || @stop
|
|
235
|
+
|
|
236
|
+
@logger.debug("[nwc] read interrupted by close: #{e.class}")
|
|
237
|
+
nil
|
|
238
|
+
end
|
|
239
|
+
break if message.nil?
|
|
204
240
|
break if @stop
|
|
205
241
|
|
|
206
242
|
begin
|
data/lib/nwc_ruby/version.rb
CHANGED