graphql-anycable 1.3.3 → 1.3.4
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/.github/workflows/test.yml +7 -3
- data/CHANGELOG.md +15 -0
- data/lib/graphql/anycable/errors.rb +4 -0
- data/lib/graphql/anycable/version.rb +1 -1
- data/lib/graphql/subscriptions/anycable_subscriptions.rb +32 -12
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8d1012a281016a5fdd02aa9a1decc2d3935f545fef5899c15505dfeef64c9628
|
|
4
|
+
data.tar.gz: ae8f4ff4cb25da208b31b8a257f60307bf66fe626362741ea29705c97bcab8e1
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3c37a74df3ffc723b7b2fcf7bbfc009b3d67df79275d1c027b22bec3c9f45d6b3a5896b270582c50fc0deb78e38c1f7bc4f38a03288aa941ac20ed584538a3c8
|
|
7
|
+
data.tar.gz: 7dff7ea7638ee30a09bbc889648db4e0ebf4a12ba2798f215b013f29bb92e146241b0a9e4cad167c4691fbe15141ef085966f4799d708352ed1729628c97d634
|
data/.github/workflows/test.yml
CHANGED
|
@@ -19,13 +19,17 @@ jobs:
|
|
|
19
19
|
matrix:
|
|
20
20
|
include:
|
|
21
21
|
- ruby: "4.0"
|
|
22
|
-
graphql: '~> 2.
|
|
22
|
+
graphql: '~> 2.6'
|
|
23
23
|
anycable: '~> 1.6'
|
|
24
24
|
redis_version: latest
|
|
25
|
+
- ruby: "3.4"
|
|
26
|
+
graphql: '~> 2.5.0'
|
|
27
|
+
anycable: '~> 1.6'
|
|
28
|
+
redis_version: '7.4'
|
|
25
29
|
- ruby: "3.3"
|
|
26
|
-
graphql: '~> 2.3'
|
|
30
|
+
graphql: '~> 2.3.0'
|
|
27
31
|
anycable: '~> 1.5'
|
|
28
|
-
redis_version:
|
|
32
|
+
redis_version: '7.4'
|
|
29
33
|
- ruby: "3.2"
|
|
30
34
|
graphql: '~> 2.2.0'
|
|
31
35
|
anycable: '~> 1.5.0'
|
data/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,20 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
|
|
7
7
|
|
|
8
8
|
## Unreleased
|
|
9
9
|
|
|
10
|
+
## 1.3.4 - 2026-08-21
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- Return `nil` from `read_subscription` if subscription data has gone from Redis, That was resulted in a "No query string was present" errors received on graphql subscription clients receiving a hash with an `nil` `query_string` instead of receiving `nil` directly. [@thlacroix] ([#51](https://github.com/anycable/graphql-anycable/pull/51))
|
|
15
|
+
|
|
16
|
+
- Subscription events are no longer dropped when another subscription with the same fingerprint expires during execution. [@prog-supdex] ([#53](https://github.com/anycable/graphql-anycable/pull/53))
|
|
17
|
+
|
|
18
|
+
- Deleting a subscription no longer goes through the deprecated `GraphQL::AnyCable.redis`; this avoids both the deprecation warning and reusing a connection after it has been returned to the pool. [@Envek] ([#53](https://github.com/anycable/graphql-anycable/pull/53))
|
|
19
|
+
|
|
20
|
+
### Changed
|
|
21
|
+
|
|
22
|
+
- `GraphQL::Subscriptions::AnyCableSubscriptions#read_subscription` now raises `GraphQL::AnyCable::SubscriptionExpiredError` when the subscription is no longer stored in Redis, instead of returning `nil`. [@Envek] ([#53](https://github.com/anycable/graphql-anycable/pull/53))
|
|
23
|
+
|
|
10
24
|
## 1.3.3 - 2026-08-10
|
|
11
25
|
|
|
12
26
|
### Fixed
|
|
@@ -231,6 +245,7 @@ Technical release to test publishing via GitHub Actions.
|
|
|
231
245
|
|
|
232
246
|
Initial version: store subscriptions on redis, re-execute queries in sync. [@Envek]
|
|
233
247
|
|
|
248
|
+
[@thlacroix]: https://github.com/thlacroix "Thomas Lacroix"
|
|
234
249
|
[@jjb]: https://github.com/jjb "John Bachir"
|
|
235
250
|
[@prog-supdex]: https://github.com/prog-supdex "Igor Platonov"
|
|
236
251
|
[@ilyasgaraev]: https://github.com/ilyasgaraev "Ilyas Garaev"
|
|
@@ -16,5 +16,9 @@ module GraphQL
|
|
|
16
16
|
DEFAULT_MESSAGE
|
|
17
17
|
end
|
|
18
18
|
end
|
|
19
|
+
|
|
20
|
+
# This error is raised when a subscription is gone from Redis by the time it is read,
|
|
21
|
+
# so that the caller can tell it from an update GraphQL has deliberately skipped.
|
|
22
|
+
class SubscriptionExpiredError < ::RuntimeError; end
|
|
19
23
|
end
|
|
20
24
|
end
|
|
@@ -95,10 +95,20 @@ module GraphQL
|
|
|
95
95
|
def execute_grouped(fingerprint, subscription_ids, event, object)
|
|
96
96
|
return if subscription_ids.empty?
|
|
97
97
|
|
|
98
|
-
|
|
99
|
-
|
|
98
|
+
result = nil
|
|
99
|
+
|
|
100
|
+
subscription_ids.each do |subscription_id|
|
|
101
|
+
result = execute_update(subscription_id, event, object)
|
|
102
|
+
|
|
103
|
+
# Whatever GraphQL has decided here — including a nil result for NO_UPDATE or
|
|
104
|
+
# for #unsubscribe without a final update — applies to the whole group, as all
|
|
105
|
+
# of its subscriptions share the same fingerprint. So, ask only one of them.
|
|
106
|
+
break
|
|
107
|
+
rescue GraphQL::AnyCable::SubscriptionExpiredError
|
|
108
|
+
# This one is gone, but the rest of the group is still waiting for the update
|
|
109
|
+
next
|
|
110
|
+
end
|
|
100
111
|
|
|
101
|
-
result = execute_update(subscription_id, event, object)
|
|
102
112
|
return unless result
|
|
103
113
|
|
|
104
114
|
# Having calculated the result _once_, send the same payload to all subscribers
|
|
@@ -162,19 +172,27 @@ module GraphQL
|
|
|
162
172
|
end
|
|
163
173
|
|
|
164
174
|
# Return the query from "storage" (in redis)
|
|
175
|
+
# @raise [GraphQL::AnyCable::SubscriptionExpiredError] if it is not stored anymore
|
|
165
176
|
def read_subscription(subscription_id)
|
|
166
|
-
with_redis do |redis|
|
|
177
|
+
subscription = with_redis do |redis|
|
|
167
178
|
redis.mapped_hmget(
|
|
168
179
|
"#{redis_key(SUBSCRIPTION_PREFIX)}#{subscription_id}",
|
|
169
180
|
:query_string, :variables, :context, :operation_name
|
|
170
|
-
)
|
|
171
|
-
next if subscription.values.all?(&:nil?) # Redis returns hash with all nils for missing key
|
|
172
|
-
|
|
173
|
-
subscription[:context] = @serializer.load(subscription[:context])
|
|
174
|
-
subscription[:variables] = JSON.parse(subscription[:variables])
|
|
175
|
-
subscription[:operation_name] = nil if subscription[:operation_name].strip == ""
|
|
176
|
-
end
|
|
181
|
+
)
|
|
177
182
|
end
|
|
183
|
+
|
|
184
|
+
# Give the connection back before raising or deserializing: a connector may be
|
|
185
|
+
# backed by a pool, and neither of these needs Redis anymore.
|
|
186
|
+
#
|
|
187
|
+
# Redis returns a hash with nil values for a missing key. A subscription without
|
|
188
|
+
# a query string is unusable anyway, so treat a half-written one as missing, too.
|
|
189
|
+
raise GraphQL::AnyCable::SubscriptionExpiredError, subscription_id if subscription[:query_string].nil?
|
|
190
|
+
|
|
191
|
+
subscription[:context] = @serializer.load(subscription[:context])
|
|
192
|
+
subscription[:variables] = JSON.parse(subscription[:variables])
|
|
193
|
+
subscription[:operation_name] = nil if subscription[:operation_name].to_s.strip == ""
|
|
194
|
+
|
|
195
|
+
subscription
|
|
178
196
|
end
|
|
179
197
|
|
|
180
198
|
# The channel was closed, forget about it and its subscriptions
|
|
@@ -194,7 +212,9 @@ module GraphQL
|
|
|
194
212
|
end
|
|
195
213
|
end
|
|
196
214
|
|
|
197
|
-
def delete_subscription(subscription_id, redis:
|
|
215
|
+
def delete_subscription(subscription_id, redis: nil)
|
|
216
|
+
return with_redis { |connection| delete_subscription(subscription_id, redis: connection) } unless redis
|
|
217
|
+
|
|
198
218
|
events = redis.hget(redis_key(SUBSCRIPTION_PREFIX) + subscription_id, :events)
|
|
199
219
|
events = events ? JSON.parse(events) : {}
|
|
200
220
|
fingerprint_subscriptions = {}
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: graphql-anycable
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.3.
|
|
4
|
+
version: 1.3.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Andrey Novikov
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-08-
|
|
11
|
+
date: 2026-08-21 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: anycable-core
|