Skip to content

Commit 9094118

Browse files
author
Robert Mosolgo
authored
Merge pull request #2993 from waysact/early-disposal
Fix issues around early disposal
2 parents cda9597 + 1ea8059 commit 9094118

File tree

2 files changed

+56
-23
lines changed

2 files changed

+56
-23
lines changed

javascript_client/src/subscriptions/__tests__/createAblyHandlerTest.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,43 @@ describe("createAblyHandler", () => {
216216
expect(nextInvokedWith).toBeUndefined()
217217
})
218218

219+
it("detaches the channel when the subscription is disposed during initial response", async () => {
220+
let detached = false
221+
222+
const ably = createDummyConsumer({
223+
...channelTemplate,
224+
detach() {
225+
detached = true
226+
}
227+
})
228+
const producer = createAblyHandler({
229+
fetchOperation: () =>
230+
new Promise(resolve =>
231+
resolve({
232+
headers: new Map([["X-Subscription-ID", "foo"]]),
233+
body: { errors: {} }
234+
})
235+
),
236+
ably
237+
})
238+
239+
const { dispose } = producer(
240+
dummyOperation,
241+
{},
242+
{},
243+
{
244+
onError: async () => {
245+
dispose()
246+
},
247+
onNext: async () => {},
248+
onCompleted: () => {}
249+
}
250+
)
251+
252+
await nextTick()
253+
expect(detached).toBe(true)
254+
})
255+
219256
describe("integration with Ably", () => {
220257
const key = process.env.ABLY_KEY
221258
const testWithAblyKey = key ? test : test.skip

javascript_client/src/subscriptions/createAblyHandler.ts

Lines changed: 19 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -68,13 +68,11 @@ function createAblyHandler(options: AblyHandlerOptions) {
6868
observer.onCompleted()
6969
}
7070
}
71-
7271
;(async () => {
7372
try {
7473
// POST the subscription like a normal query
7574
const response = await fetchOperation(operation, variables, cacheConfig)
7675

77-
dispatchResult(response.body)
7876
const channelName = response.headers.get("X-Subscription-ID")
7977
if (!channelName) {
8078
throw new Error("Missing X-Subscription-ID header")
@@ -123,6 +121,8 @@ function createAblyHandler(options: AblyHandlerOptions) {
123121
}
124122
// When you get an update from ably, give it to Relay
125123
channel.subscribe("update", updateHandler)
124+
125+
dispatchResult(response.body)
126126
} catch (error) {
127127
observer.onError(error)
128128
}
@@ -133,28 +133,25 @@ function createAblyHandler(options: AblyHandlerOptions) {
133133
try {
134134
if (channel) {
135135
const disposedChannel = channel
136-
disposedChannel.unsubscribe("update", updateHandler)
137-
138-
const leavePromise = new Promise((resolve, reject) => {
139-
const callback = (err: Types.ErrorInfo) => {
140-
if (err) {
141-
reject(new AblyError(err))
142-
} else {
143-
resolve()
136+
disposedChannel.unsubscribe()
137+
138+
// Ensure channel is no longer attaching, as otherwise detach does
139+
// nothing
140+
if (disposedChannel.state === "attaching") {
141+
await new Promise((resolve, _reject) => {
142+
const onStateChange = (
143+
stateChange: Types.ChannelStateChange
144+
) => {
145+
if (stateChange.current !== "attaching") {
146+
disposedChannel.off(onStateChange)
147+
resolve()
148+
}
144149
}
145-
}
146-
147-
if (isAnonymousClient()) {
148-
disposedChannel.presence.leaveClient(
149-
anonymousClientId,
150-
callback
151-
)
152-
} else {
153-
disposedChannel.presence.leave(callback)
154-
}
155-
})
150+
disposedChannel.on(onStateChange)
151+
})
152+
}
156153

157-
const detachPromise = new Promise((resolve, reject) => {
154+
await new Promise((resolve, reject) => {
158155
disposedChannel.detach((err: Types.ErrorInfo) => {
159156
if (err) {
160157
reject(new AblyError(err))
@@ -164,7 +161,6 @@ function createAblyHandler(options: AblyHandlerOptions) {
164161
})
165162
})
166163

167-
await Promise.all([leavePromise, detachPromise])
168164
ably.channels.release(disposedChannel.name)
169165
}
170166
} catch (error) {

0 commit comments

Comments
 (0)