Skip to content

Commit 28ecb59

Browse files
committed
WorkflowService: Fix TypeError when unsubscribing
This affected the log view when switching between workflow & job logs.
1 parent 2dd0d22 commit 28ecb59

File tree

4 files changed

+32
-31
lines changed

4 files changed

+32
-31
lines changed

src/mixins/subscriptionComponent.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,11 @@ export default {
4949
this._updateQuery(null, this.query)
5050
},
5151
methods: {
52-
_updateQuery (newVal, oldVal) {
53-
if (oldVal) {
54-
this.$workflowService.unsubscribe(this)
52+
_updateQuery (newQuery, oldQuery) {
53+
if (oldQuery) {
54+
this.$workflowService.unsubscribe(oldQuery, this._uid)
5555
}
56-
if (newVal) {
56+
if (newQuery) {
5757
this.$workflowService.subscribe(this)
5858
this.$workflowService.startSubscriptions()
5959
}

src/services/workflow.service.js

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -194,25 +194,20 @@ class WorkflowService {
194194
// --- GraphQL query subscriptions
195195

196196
/**
197-
* @param {View} componentOrView
197+
* @param {SubscriptionQuery} query
198198
* @returns {Subscription}
199199
*/
200-
getOrCreateSubscription (componentOrView) {
201-
const queryName = componentOrView.query.name
202-
let subscription = this.subscriptions[queryName]
200+
getOrCreateSubscription (query) {
203201
// note, this will force a return of the FIRST query of the SAME name as any subsequent queries
204-
if (!subscription) {
205-
subscription = this.subscriptions[queryName] = new Subscription(componentOrView.query)
206-
}
207-
return subscription
202+
return (this.subscriptions[query.name] ??= new Subscription(query))
208203
}
209204

210205
/**
211206
* @param {View} componentOrView
212207
*/
213208
subscribe (componentOrView) {
214209
// First we retrieve the existing, or create a new subscription (and add to the pool).
215-
const subscription = this.getOrCreateSubscription(componentOrView)
210+
const subscription = this.getOrCreateSubscription(componentOrView.query)
216211
if (!subscription.subscribers[componentOrView._uid]) {
217212
// NOTE: make sure to remove it afterwards to avoid memory leaks!
218213
subscription.subscribers[componentOrView._uid] = componentOrView
@@ -398,15 +393,21 @@ class WorkflowService {
398393
})
399394
}
400395

401-
unsubscribe (componentOrView) {
402-
const subscription = this.subscriptions[componentOrView.query.name]
396+
/**
397+
* Remove subscriber and stop subscription.
398+
*
399+
* @param {SubscriptionQuery} query - The component/view's subscription query.
400+
* @param {string} uid - The unique ID for the component/view.
401+
*/
402+
unsubscribe (query, uid) {
403+
const subscription = this.subscriptions[query.name]
403404
if (!subscription) {
404405
// eslint-disable-next-line no-console
405-
console.warn(`Could not unsubscribe [${componentOrView.query.name}]: Not Found`)
406+
console.warn(`Could not unsubscribe [${query.name}]: Not Found`)
406407
return
407408
}
408409
// Remove viewOrComponent subscriber
409-
delete subscription.subscribers[componentOrView._uid]
410+
delete subscription.subscribers[uid]
410411
// If no more subscribers, then stop the subscription.
411412
if (Object.keys(subscription.subscribers).length === 0) {
412413
this.stopSubscription(subscription)

tests/unit/mixins/subscriptionComponent.spec.js

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import sinon from 'sinon'
1919
import { mount } from '@vue/test-utils'
2020
import subscriptionComponentMixin from '@/mixins/subscriptionComponent'
2121
import WorkflowService from '@/services/workflow.service'
22+
import { cloneDeep } from 'lodash'
2223

2324
describe('Subscription Component mixin', () => {
2425
let $workflowService, component
@@ -40,17 +41,20 @@ describe('Subscription Component mixin', () => {
4041
})
4142

4243
it('subscribes & unsubscribes when the component is mounted & destroyed', () => {
43-
expect($workflowService.subscribe.calledOnceWith(component.vm)).to.equal(true)
44+
const { vm } = component
45+
expect($workflowService.subscribe.calledOnceWith(vm)).to.equal(true)
4446
expect($workflowService.startSubscriptions.calledOnce).to.equal(true)
4547
expect($workflowService.unsubscribe.called).to.equal(false)
4648
component.unmount()
47-
expect($workflowService.unsubscribe.calledOnceWith(component.vm)).to.equal(true)
49+
expect($workflowService.unsubscribe.calledOnceWith(vm.query, vm._uid)).to.equal(true)
4850
})
4951

5052
it('un- & re-subcribes when the query changes', () => {
51-
component.vm.query = { foo: 2 }
52-
component.vm.$nextTick(() => {
53-
expect($workflowService.unsubscribe.calledOnceWith(component.vm)).to.equal(true)
53+
const { vm } = component
54+
const oldQuery = cloneDeep(vm.query)
55+
vm.query = { foo: 2 }
56+
vm.$nextTick(() => {
57+
expect($workflowService.unsubscribe.calledOnceWith(oldQuery, vm._uid)).to.equal(true)
5458
expect($workflowService.subscribe.calledTwice).to.equal(true)
5559
expect($workflowService.startSubscriptions.calledTwice).to.equal(true)
5660
})

tests/unit/services/workflow.service.spec.js

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -130,13 +130,13 @@ describe('WorkflowService', () => {
130130
})
131131
describe('getOrCreateSubscription', () => {
132132
it('should return existing subscriptions', () => {
133-
const existingSubscription = service.getOrCreateSubscription(view)
133+
const existingSubscription = service.getOrCreateSubscription(view.query)
134134
expect(existingSubscription).to.deep.equal(subscription)
135135
})
136136
it('should create new subscriptions and add to local cache', () => {
137137
delete service.subscriptions[view.query.name]
138138
expect(Object.keys(service.subscriptions).length).to.equal(0)
139-
const newSubscription = service.getOrCreateSubscription(view)
139+
const newSubscription = service.getOrCreateSubscription(view.query)
140140
expect(Object.keys(service.subscriptions).length).to.equal(1)
141141
expect(service.subscriptions[view.query.name]).to.deep.equal(newSubscription)
142142
})
@@ -343,16 +343,12 @@ describe('WorkflowService', () => {
343343
describe('unsubscribe', () => {
344344
it('should warn about queries that do not exist', () => {
345345
const stub = sandbox.stub(console, 'warn')
346-
service.unsubscribe({
347-
query: {
348-
name: 'missing'
349-
}
350-
})
346+
service.unsubscribe({ name: 'missing' }, 'irrelevant_uid')
351347
expect(stub.calledOnce).to.equal(true)
352348
})
353349
it('should call unsubscribe if last subscriber is unsubscribed', () => {
354350
const stub = sandbox.stub(service, 'stopSubscription')
355-
service.unsubscribe(view)
351+
service.unsubscribe(view.query, view._uid)
356352
expect(stub.calledOnce).to.equal(true)
357353
})
358354
it('should NOT call unsubscribe if there are still subscribers left', () => {
@@ -362,7 +358,7 @@ describe('WorkflowService', () => {
362358
}
363359
service.subscribe(anotherView)
364360
const stub = sandbox.stub(service, 'stopSubscription')
365-
service.unsubscribe(view)
361+
service.unsubscribe(view.query, view._uid)
366362
expect(stub.calledOnce).to.equal(false)
367363
})
368364
})

0 commit comments

Comments
 (0)