diff --git a/javascript_client/src/subscriptions/ActionCableLink.ts b/javascript_client/src/subscriptions/ActionCableLink.ts index 1ca596864d..798ef49b27 100644 --- a/javascript_client/src/subscriptions/ActionCableLink.ts +++ b/javascript_client/src/subscriptions/ActionCableLink.ts @@ -11,15 +11,6 @@ type SubscriptionCallbacks = { }; type CreateChannelId = () => string - -function createChannelId() { - // `crypto.randomUUID()` (Web Crypto API) is used because a low-entropy - // identifier here can collide between simultaneously-created subscriptions, - // and ActionCable routes incoming payloads by identifier — colliding - // subscriptions would receive each other's payloads. - return crypto.randomUUID() -} - class ActionCableLink extends ApolloLink { cable: Consumer channelName: string @@ -42,7 +33,7 @@ class ActionCableLink extends ApolloLink { this.actionName = options.actionName || "execute" this.connectionParams = options.connectionParams || {} this.callbacks = options.callbacks || {} - this.createChannelId = options.createChannelId || createChannelId + this.createChannelId = options.createChannelId || crypto.randomUUID.bind(crypto) } // Interestingly, this link does _not_ call through to `next` because diff --git a/javascript_client/src/subscriptions/ActionCableSubscriber.ts b/javascript_client/src/subscriptions/ActionCableSubscriber.ts index 75711734ec..6d9e786243 100644 --- a/javascript_client/src/subscriptions/ActionCableSubscriber.ts +++ b/javascript_client/src/subscriptions/ActionCableSubscriber.ts @@ -8,15 +8,19 @@ interface ApolloNetworkInterface { _opts: any } +type CreateChannelId = () => string + class ActionCableSubscriber { _cable: Consumer _networkInterface: ApolloNetworkInterface _channelName: string + _createChannelId: CreateChannelId - constructor(cable: Consumer, networkInterface: ApolloNetworkInterface, channelName?: string) { + constructor(cable: Consumer, networkInterface: ApolloNetworkInterface, channelName?: string, createChannelId?: CreateChannelId) { this._cable = cable this._networkInterface = networkInterface this._channelName = channelName || "GraphqlChannel" + this._createChannelId = createChannelId || crypto.randomUUID.bind(crypto) } /** @@ -31,7 +35,7 @@ class ActionCableSubscriber { subscribe(request: any, handler: any) { var networkInterface = this._networkInterface // unique-ish - var channelId = Math.round(Date.now() + Math.random() * 100000).toString(16) + var channelId = this._createChannelId() var channel = this._cable.subscriptions.create({ channel: this._channelName, channelId: channelId, diff --git a/javascript_client/src/subscriptions/createActionCableHandler.ts b/javascript_client/src/subscriptions/createActionCableHandler.ts index 4f2668473a..17b2367d9f 100644 --- a/javascript_client/src/subscriptions/createActionCableHandler.ts +++ b/javascript_client/src/subscriptions/createActionCableHandler.ts @@ -12,12 +12,13 @@ interface ActionCableHandlerOptions { operations?: { getOperationId: Function} channelName?: string clientName?: string + createChannelId?: () => string } function createActionCableHandler(options: ActionCableHandlerOptions) { + const createChannelId = options.createChannelId || crypto.randomUUID.bind(crypto) return function (operation: { text: string, name: string, id?: string }, variables: object, _cacheConfig: object, observer: {onError: Function, onNext: Function, onCompleted: Function}) { - // unique-ish - var channelId = Math.round(Date.now() + Math.random() * 100000).toString(16) + var channelId = createChannelId() var cable = options.cable var operations = options.operations var subscribed = true diff --git a/spec/dummy/app/assets/javascripts/application.js b/spec/dummy/app/assets/javascripts/application.js index 2690222b6c..8a71c04fa8 100644 --- a/spec/dummy/app/assets/javascripts/application.js +++ b/spec/dummy/app/assets/javascripts/application.js @@ -25,8 +25,7 @@ var query = options.query var variables = options.variables var receivedCallback = options.received - // Unique-ish - var uuid = Math.round(Date.now() + Math.random() * 100000).toString(16) + var uuid = crypto.randomUUID() var subscription = { _subscribed: false, subscription: App.cable.subscriptions.create({