Passed
Push — trunk ( f1db29...787632 )
by Christian
12:08 queued 12s
created

worker.init.ts ➔ messageQueueNotification   C

Complexity

Conditions 7

Size

Total Lines 77
Code Lines 62

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 62
dl 0
loc 77
rs 6.8436
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
import AdminWorker from 'src/core/worker/admin-worker.worker';
2
import WorkerNotificationListener from 'src/core/worker/worker-notification-listener';
3
import AdminNotificationWorker from 'src/core/worker/admin-notification-worker';
4
import getRefreshTokenHelper from 'src/core/helper/refresh-token.helper';
5
import type { ApiContext } from '@shopware-ag/admin-extension-sdk/es/data/_internals/EntityCollection';
6
import type Vue from 'vue';
7
import type { LoginService } from '../../core/service/login.service';
8
import type { ContextState } from '../state/context.store';
9
import type {
10
    NotificationConfig,
11
    NotificationService,
12
    NotificationWorkerOptions,
13
} from '../../core/factory/worker-notification.factory';
14
import type WorkerNotificationFactory from '../../core/factory/worker-notification.factory';
15
16
let enabled = false;
17
let enabledNotification = false;
18
19
/**
20
 * @package admin
21
 *
22
 * Starts the worker
23
 */
24
// eslint-disable-next-line sw-deprecation-rules/private-feature-declarations
25
export default function initializeWorker() {
26
    const loginService = Shopware.Service('loginService');
27
    const context = Shopware.Context.app;
28
    const workerNotificationFactory = Shopware.Application.getContainer('factory').workerNotification;
29
    const configService = Shopware.Service('configService');
30
31
    registerThumbnailMiddleware(workerNotificationFactory);
32
33
    function getConfig() {
34
        return configService.getConfig().then((response) => {
35
            Object.entries(response as { [key: string]: unknown}).forEach(([key, value]) => {
36
                Shopware.State.commit('context/addAppConfigValue', { key, value });
37
            });
38
39
            // Enable worker notification listener regardless of the config
40
            enableWorkerNotificationListener(
41
                loginService,
42
                Shopware.Context.api,
43
            );
44
45
            // Enable worker notification listener regardless of the config
46
            if (!enabledNotification) {
47
                enableNotificationWorker(loginService);
48
            }
49
50
            if (context.config.adminWorker?.enableAdminWorker && !enabled) {
51
                enableAdminWorker(loginService, Shopware.Context.api, context.config.adminWorker);
52
            }
53
        });
54
    }
55
56
    if (loginService.isLoggedIn()) {
57
        return getConfig().catch();
58
    }
59
60
    return loginService.addOnLoginListener(getConfig);
61
}
62
63
function enableAdminWorker(
64
    loginService: LoginService,
65
    context: ApiContext,
66
    config: ContextState['app']['config']['adminWorker'],
67
) {
68
    const getMessage = () => {
69
        return {
70
            context: {
71
                languageId: context.languageId,
72
                apiResourcePath: context.apiResourcePath,
73
            },
74
            bearerAuth: loginService.getBearerAuthentication(),
75
            host: window.location.origin,
76
            transports: config?.transports || [],
77
        };
78
    };
79
80
    if (loginService.isLoggedIn()) {
81
        getWorker().postMessage(getMessage());
82
    }
83
84
    loginService.addOnTokenChangedListener((auth) => {
85
        getWorker().postMessage({ ...getMessage(), ...{ bearerAuth: auth } });
86
    });
87
88
    loginService.addOnLogoutListener(() => {
89
        getWorker().postMessage({ type: 'logout' });
90
    });
91
92
    const importExportService = Shopware.Service('importExport');
93
94
    importExportService.addOnProgressStartedListener(() => {
95
        getWorker().postMessage({ ...getMessage(), ...{ type: 'consumeReset' } });
96
    });
97
98
    enabled = true;
99
}
100
101
// singleton instance of worker
102
let worker: Worker;
103
104
/* istanbul ignore next */
105
function getWorker() : Worker {
106
    if (worker) {
107
        return worker;
108
    }
109
110
    // The webpack worker plugin generates a valid worker file therefore we can use it here
111
    // @ts-expect-error
112
    worker = new AdminWorker() as Worker;
113
114
    worker.onmessage = () => {
115
        const tokenHandler = getRefreshTokenHelper();
116
117
        if (!tokenHandler.isRefreshing) {
118
            void tokenHandler.fireRefreshTokenRequest();
119
        }
120
    };
121
122
    return worker;
123
}
124
125
function enableWorkerNotificationListener(loginService: LoginService, context: ContextState['api']) {
126
    let workerNotificationListener = new WorkerNotificationListener(context);
127
128
    if (loginService.isLoggedIn()) {
129
        workerNotificationListener.start();
130
    }
131
132
    loginService.addOnTokenChangedListener(() => {
133
        workerNotificationListener.terminate();
134
        workerNotificationListener = new WorkerNotificationListener(context);
135
        workerNotificationListener.start();
136
    });
137
138
    loginService.addOnLogoutListener(() => {
139
        workerNotificationListener.terminate();
140
        workerNotificationListener = new WorkerNotificationListener(context);
141
    });
142
}
143
144
function enableNotificationWorker(loginService: LoginService) {
145
    let notificationWorker = new AdminNotificationWorker();
146
147
    if (loginService.isLoggedIn()) {
148
        notificationWorker.start();
149
    }
150
151
    loginService.addOnTokenChangedListener(() => {
152
        notificationWorker.terminate();
153
        notificationWorker = new AdminNotificationWorker();
154
        notificationWorker.start();
155
    });
156
157
    loginService.addOnLogoutListener(() => {
158
        notificationWorker.terminate();
159
        notificationWorker = new AdminNotificationWorker();
160
    });
161
162
    enabledNotification = true;
163
}
164
165
function registerThumbnailMiddleware(factory: typeof WorkerNotificationFactory) {
166
    const ids = {};
167
    factory.register('DalIndexingMessage', {
168
        name: 'Shopware\\Core\\Framework\\DataAbstractionLayer\\Indexing\\MessageQueue\\IndexerMessage',
169
        fn: function middleware(next, { entry, $root, notification }) {
170
            messageQueueNotification('dalIndexing', ids, next, entry, $root, notification, {
171
                title: 'global.default.success',
172
                message: 'global.notification-center.worker-listener.dalIndexing.message',
173
                success: 'global.notification-center.worker-listener.dalIndexing.messageSuccess',
174
                foregroundSuccessMessage: 'sw-settings-cache.notifications.index.success',
175
            });
176
        },
177
    });
178
179
    factory.register('WarmupIndexingMessage', {
180
        name: 'Shopware\\Storefront\\Framework\\Cache\\CacheWarmer\\WarmUpMessage',
181
        fn: function middleware(next, { entry, $root, notification }) {
182
            messageQueueNotification('warmupMessage', ids, next, entry, $root, notification, {
183
                title: 'global.default.success',
184
                message: 'global.notification-center.worker-listener.warmupIndexing.message',
185
                success: 'global.notification-center.worker-listener.warmupIndexing.messageSuccess',
186
                foregroundSuccessMessage: 'sw-settings-cache.notifications.clearCacheAndWarmup.success',
187
            }, 10);
188
        },
189
    });
190
191
    factory.register('EsIndexingMessage', {
192
        name: 'Shopware\\Elasticsearch\\Framework\\Indexing\\IndexingMessage',
193
        fn: function middleware(next, { entry, $root, notification }) {
194
            messageQueueNotification('esIndexing', ids, next, entry, $root, notification, {
195
                title: 'global.default.success',
196
                message: 'global.notification-center.worker-listener.esIndexing.message',
197
                success: 'global.notification-center.worker-listener.esIndexing.messageSuccess',
198
            });
199
        },
200
    });
201
202
    factory.register('generateThumbnailsMessage', {
203
        name: 'Shopware\\Core\\Content\\Media\\Message\\GenerateThumbnailsMessage',
204
        fn: function middleware(next, { entry, $root, notification }) {
205
            messageQueueNotification('thumbnails', ids, next, entry, $root, notification, {
206
                title: 'global.notification-center.worker-listener.thumbnailGeneration.title',
207
                message: 'global.notification-center.worker-listener.thumbnailGeneration.message',
208
                success: 'global.notification-center.worker-listener.thumbnailGeneration.messageSuccess',
209
            });
210
        },
211
    });
212
213
    factory.register('PromotionIndexingMessage', {
214
        name: 'Shopware\\Core\\Checkout\\Promotion\\DataAbstractionLayer\\PromotionIndexingMessage',
215
        fn: function middleware(next, { entry, $root, notification }) {
216
            messageQueueNotification('promotion', ids, next, entry, $root, notification, {
217
                title: 'global.notification-center.worker-listener.promotion.title',
218
                message: 'global.notification-center.worker-listener.promotion.message',
219
                success: 'global.notification-center.worker-listener.promotion.messageSuccess',
220
            }, 50);
221
        },
222
    });
223
224
    factory.register('ProductStreamIndexingMessage', {
225
        name: 'Shopware\\Core\\Content\\ProductStream\\DataAbstractionLayer\\ProductStreamIndexingMessage',
226
        fn: function middleware(next, { entry, $root, notification }) {
227
            messageQueueNotification('productStream', ids, next, entry, $root, notification, {
228
                title: 'global.notification-center.worker-listener.productStream.title',
229
                message: 'global.notification-center.worker-listener.productStream.message',
230
                success: 'global.notification-center.worker-listener.productStream.messageSuccess',
231
            }, 50);
232
        },
233
    });
234
235
    factory.register('CategoryIndexingMessage', {
236
        name: 'Shopware\\Core\\Content\\Category\\DataAbstractionLayer\\CategoryIndexingMessage',
237
        fn: function middleware(next, { entry, $root, notification }) {
238
            messageQueueNotification('category', ids, next, entry, $root, notification, {
239
                title: 'global.notification-center.worker-listener.category.title',
240
                message: 'global.notification-center.worker-listener.category.message',
241
                success: 'global.notification-center.worker-listener.category.messageSuccess',
242
            }, 50);
243
        },
244
    });
245
246
    factory.register('MediaIndexingMessage', {
247
        name: 'Shopware\\Core\\Content\\Media\\DataAbstractionLayer\\MediaIndexingMessage',
248
        fn: function middleware(next, { entry, $root, notification }) {
249
            messageQueueNotification('media', ids, next, entry, $root, notification, {
250
                title: 'global.notification-center.worker-listener.media.title',
251
                message: 'global.notification-center.worker-listener.media.message',
252
                success: 'global.notification-center.worker-listener.media.messageSuccess',
253
            }, 50);
254
        },
255
    });
256
257
    factory.register('SalesChannelIndexingMessage', {
258
        name: 'Shopware\\Core\\System\\SalesChannel\\DataAbstractionLayer\\SalesChannelIndexingMessage',
259
        fn: function middleware(next, { entry, $root, notification }) {
260
            messageQueueNotification('salesChannel', ids, next, entry, $root, notification, {
261
                title: 'global.notification-center.worker-listener.salesChannel.title',
262
                message: 'global.notification-center.worker-listener.salesChannel.message',
263
                success: 'global.notification-center.worker-listener.salesChannel.messageSuccess',
264
            }, 50);
265
        },
266
    });
267
268
    factory.register('RuleIndexingMessage', {
269
        name: 'Shopware\\Core\\Content\\Rule\\DataAbstractionLayer\\RuleIndexingMessage',
270
        fn: function middleware(next, { entry, $root, notification }) {
271
            messageQueueNotification('rule', ids, next, entry, $root, notification, {
272
                title: 'global.notification-center.worker-listener.rule.title',
273
                message: 'global.notification-center.worker-listener.rule.message',
274
                success: 'global.notification-center.worker-listener.rule.messageSuccess',
275
            }, 50);
276
        },
277
    });
278
279
    factory.register('ProductIndexingMessage', {
280
        name: 'Shopware\\Core\\Content\\Product\\DataAbstractionLayer\\ProductIndexingMessage',
281
        fn: function middleware(next, { entry, $root, notification }) {
282
            messageQueueNotification('product', ids, next, entry, $root, notification, {
283
                title: 'global.notification-center.worker-listener.product.title',
284
                message: 'global.notification-center.worker-listener.product.message',
285
                success: 'global.notification-center.worker-listener.product.messageSuccess',
286
            }, 50);
287
        },
288
    });
289
290
    factory.register('ElasticSearchIndexingMessage', {
291
        name: 'Shopware\\Elasticsearch\\Framework\\Indexing\\ElasticsearchIndexingMessage',
292
        fn: function middleware(next, { entry, $root, notification }) {
293
            messageQueueNotification('esIndexing', ids, next, entry, $root, notification, {
294
                title: 'global.default.success',
295
                message: 'global.notification-center.worker-listener.esIndexing.message',
296
                success: 'global.notification-center.worker-listener.esIndexing.messageSuccess',
297
            }, 50);
298
        },
299
    });
300
301
    factory.register('ImportExportMessage', {
302
        name: 'Shopware\\Core\\Content\\ImportExport\\Message\\ImportExportMessage',
303
        fn: function middleware(next, { entry, $root, notification }) {
304
            messageQueueNotification('importExport', ids, next, entry, $root, notification, {
305
                title: 'global.notification-center.worker-listener.importExport.title',
306
                message: 'global.notification-center.worker-listener.importExport.message',
307
                success: 'global.notification-center.worker-listener.importExport.messageSuccess',
308
            });
309
        },
310
    });
311
312
    factory.register('FlowIndexingMessage', {
313
        name: 'Shopware\\Core\\Content\\Flow\\Indexing\\FlowIndexingMessage',
314
        fn: function middleware(next, { entry, $root, notification }) {
315
            messageQueueNotification('flow', ids, next, entry, $root, notification, {
316
                title: 'global.notification-center.worker-listener.flow.title',
317
                message: 'global.notification-center.worker-listener.flow.message',
318
                success: 'global.notification-center.worker-listener.flow.messageSuccess',
319
            });
320
        },
321
    });
322
323
    factory.register('NewsletterRecipientIndexingMessage', {
324
        name: 'Shopware\\Core\\Content\\Newsletter\\DataAbstractionLayer\\NewsletterRecipientIndexingMessage',
325
        fn: function middleware(next, { entry, $root, notification }) {
326
            messageQueueNotification('newsletterRecipient', ids, next, entry, $root, notification, {
327
                title: 'global.notification-center.worker-listener.newsletterRecipient.title',
328
                message: 'global.notification-center.worker-listener.newsletterRecipient.message',
329
                success: 'global.notification-center.worker-listener.newsletterRecipient.messageSuccess',
330
            });
331
        },
332
    });
333
334
    return true;
335
}
336
337
function messageQueueNotification(
338
    key: string,
339
    ids: { [key: string]: { notificationId: string, didSendForegroundMessage: boolean}},
340
    next: (name?: string, opts?: NotificationWorkerOptions) => unknown,
341
    entry: { size: number },
342
    $root: Vue,
343
    notification: NotificationService,
344
    messages: { title: string, message: string, success: string, foregroundSuccessMessage?: string },
345
    multiplier = 1,
346
) {
347
    let notificationId = null;
348
    let didSendForegroundMessage = false;
349
350
    if (ids.hasOwnProperty((key))) {
351
        notificationId = ids[key].notificationId;
352
        didSendForegroundMessage = ids[key].didSendForegroundMessage;
353
    }
354
355
    if (entry.size) {
356
        entry.size *= multiplier;
357
    }
358
359
360
    const config: NotificationConfig = {
361
        title: $root.$tc(messages.title),
362
        message: $root.$tc(messages.message, entry.size),
363
        variant: 'info',
364
        metadata: {
365
            size: entry.size,
366
        },
367
        growl: false,
368
        isLoading: true,
369
    };
370
371
    // Create new notification
372
    if (entry.size && notificationId === null) {
373
        void notification.create(config).then((uuid) => {
374
            notificationId = uuid;
375
376
            ids[key] = {
377
                notificationId,
378
                didSendForegroundMessage: false,
379
            };
380
        });
381
        next();
382
    }
383
384
    // Update existing notification
385
    if (notificationId !== null) {
386
        config.uuid = notificationId;
387
388
        if (entry.size === 0) {
389
            config.title = $root.$tc(messages.title);
390
            config.message = $root.$t(messages.success) as string;
391
            config.isLoading = false;
392
393
            if (messages.foregroundSuccessMessage && !didSendForegroundMessage) {
394
                const foreground = { ...config };
395
                foreground.message = $root.$t(messages.foregroundSuccessMessage) as string;
396
                delete foreground.uuid;
397
                delete foreground.isLoading;
398
                foreground.growl = true;
399
                foreground.variant = 'success';
400
                void notification.create(foreground);
401
402
                ids[key] = {
403
                    notificationId,
404
                    didSendForegroundMessage: true,
405
                };
406
            }
407
408
            delete ids[key];
409
        }
410
        void notification.update(config);
411
    }
412
    next();
413
}
414