@webex/internal-plugin-device 3.12.0-next.8 → 3.12.0-task-refactor.1
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.
- package/dist/config.js +10 -16
- package/dist/config.js.map +1 -1
- package/dist/constants.js +1 -6
- package/dist/constants.js.map +1 -1
- package/dist/device.js +79 -181
- package/dist/device.js.map +1 -1
- package/dist/ipNetworkDetector.js +3 -3
- package/dist/ipNetworkDetector.js.map +1 -1
- package/package.json +10 -10
- package/src/config.js +9 -16
- package/src/constants.js +0 -5
- package/src/device.js +26 -150
- package/src/ipNetworkDetector.ts +1 -1
- package/test/unit/spec/device.js +46 -641
package/src/device.js
CHANGED
|
@@ -6,13 +6,7 @@ import {orderBy} from 'lodash';
|
|
|
6
6
|
import uuid from 'uuid';
|
|
7
7
|
|
|
8
8
|
import METRICS from './metrics';
|
|
9
|
-
import {
|
|
10
|
-
FEATURE_COLLECTION_NAMES,
|
|
11
|
-
DEVICE_EVENT_REGISTRATION_SUCCESS,
|
|
12
|
-
MIN_DEVICES_FOR_CLEANUP,
|
|
13
|
-
MAX_DELETION_CONFIRMATION_ATTEMPTS,
|
|
14
|
-
DELETION_CONFIRMATION_DELAY_MS,
|
|
15
|
-
} from './constants';
|
|
9
|
+
import {FEATURE_COLLECTION_NAMES, DEVICE_EVENT_REGISTRATION_SUCCESS} from './constants';
|
|
16
10
|
import FeaturesModel from './features/features-model';
|
|
17
11
|
import IpNetworkDetector from './ipNetworkDetector';
|
|
18
12
|
import {CatalogDetails} from './types';
|
|
@@ -460,117 +454,46 @@ const Device = WebexPlugin.extend({
|
|
|
460
454
|
});
|
|
461
455
|
},
|
|
462
456
|
/**
|
|
463
|
-
* Fetches devices
|
|
464
|
-
* @returns {Promise<
|
|
457
|
+
* Fetches the web devices and deletes the third of them which are not recent devices in use
|
|
458
|
+
* @returns {Promise<void, Error>}
|
|
465
459
|
*/
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
460
|
+
deleteDevices() {
|
|
461
|
+
// Fetch devices with a GET request
|
|
469
462
|
return this.request({
|
|
470
463
|
method: 'GET',
|
|
471
464
|
service: 'wdm',
|
|
472
465
|
resource: 'devices',
|
|
473
|
-
})
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
/**
|
|
477
|
-
* Waits until the server-side device count drops to or below targetCount,
|
|
478
|
-
* polling up to maxAttempts times with a delay between each check.
|
|
479
|
-
* @param {number} targetCount - resolve when device count drops to this value or below
|
|
480
|
-
* @param {number} [attempt=0]
|
|
481
|
-
* @returns {Promise<void>}
|
|
482
|
-
*/
|
|
483
|
-
_waitForDeviceCountBelowLimit(targetCount, attempt = 0) {
|
|
484
|
-
if (attempt >= MAX_DELETION_CONFIRMATION_ATTEMPTS) {
|
|
485
|
-
this.logger.warn('device: max confirmation attempts reached, proceeding anyway');
|
|
486
|
-
|
|
487
|
-
return Promise.resolve();
|
|
488
|
-
}
|
|
489
|
-
|
|
490
|
-
return new Promise((resolve) => setTimeout(resolve, DELETION_CONFIRMATION_DELAY_MS))
|
|
491
|
-
.then(() => this._getDevicesOfCurrentType())
|
|
492
|
-
.then((devices) => {
|
|
493
|
-
this.logger.info(
|
|
494
|
-
`device: confirmation check ${attempt + 1}/${MAX_DELETION_CONFIRMATION_ATTEMPTS}, ` +
|
|
495
|
-
`${devices.length} devices remaining (target: ≤ ${targetCount})`
|
|
496
|
-
);
|
|
497
|
-
|
|
498
|
-
if (devices.length <= targetCount) {
|
|
499
|
-
this.logger.info('device: device count is now safely below limit');
|
|
500
|
-
|
|
501
|
-
return Promise.resolve();
|
|
502
|
-
}
|
|
503
|
-
|
|
504
|
-
return this._waitForDeviceCountBelowLimit(targetCount, attempt + 1);
|
|
505
|
-
})
|
|
506
|
-
.catch((error) => {
|
|
507
|
-
this.logger.warn(
|
|
508
|
-
`device: confirmation check ${attempt + 1} failed, proceeding anyway:`,
|
|
509
|
-
error
|
|
510
|
-
);
|
|
466
|
+
})
|
|
467
|
+
.then((response) => {
|
|
468
|
+
const {devices} = response.body;
|
|
511
469
|
|
|
512
|
-
|
|
513
|
-
});
|
|
514
|
-
},
|
|
470
|
+
const {deviceType} = this._getBody();
|
|
515
471
|
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
* for the server to confirm the count is below the limit.
|
|
519
|
-
* @returns {Promise<void>}
|
|
520
|
-
*/
|
|
521
|
-
deleteDevices() {
|
|
522
|
-
let targetCount;
|
|
472
|
+
// Filter devices of type deviceType
|
|
473
|
+
const webDevices = devices.filter((item) => item.deviceType === deviceType);
|
|
523
474
|
|
|
524
|
-
return this._getDevicesOfCurrentType()
|
|
525
|
-
.then((webDevices) => {
|
|
526
475
|
const sortedDevices = orderBy(webDevices, [(item) => new Date(item.modificationTime)]);
|
|
527
476
|
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
477
|
+
// If there are more than two devices, delete the last third
|
|
478
|
+
if (sortedDevices.length > 2) {
|
|
479
|
+
const totalItems = sortedDevices.length;
|
|
480
|
+
const countToDelete = Math.ceil(totalItems / 3);
|
|
481
|
+
const urlsToDelete = sortedDevices.slice(0, countToDelete).map((item) => item.url);
|
|
482
|
+
|
|
483
|
+
return Promise.race(
|
|
484
|
+
urlsToDelete.map((url) => {
|
|
485
|
+
return this.request({
|
|
486
|
+
uri: url,
|
|
487
|
+
method: 'DELETE',
|
|
488
|
+
});
|
|
489
|
+
})
|
|
531
490
|
);
|
|
532
|
-
|
|
533
|
-
return Promise.resolve();
|
|
534
491
|
}
|
|
535
492
|
|
|
536
|
-
|
|
537
|
-
targetCount = sortedDevices.length - Math.min(5, devicesToDelete.length);
|
|
538
|
-
|
|
539
|
-
this.logger.info(
|
|
540
|
-
`device: deleting ${devicesToDelete.length} of ${webDevices.length} devices`
|
|
541
|
-
);
|
|
542
|
-
|
|
543
|
-
return Promise.all(
|
|
544
|
-
devicesToDelete.map((device) =>
|
|
545
|
-
this.request({uri: device.url, method: 'DELETE'})
|
|
546
|
-
.then(() => ({status: 'fulfilled'}))
|
|
547
|
-
.catch((reason) => ({status: 'rejected', reason}))
|
|
548
|
-
)
|
|
549
|
-
).then((results) => {
|
|
550
|
-
const failed = results.filter((r) => r.status === 'rejected');
|
|
551
|
-
|
|
552
|
-
if (failed.length > 0) {
|
|
553
|
-
this.logger.warn(
|
|
554
|
-
`device: ${failed.length} of ${devicesToDelete.length} deletions failed (best-effort, continuing)`
|
|
555
|
-
);
|
|
556
|
-
}
|
|
557
|
-
this.logger.info(
|
|
558
|
-
`device: deleted ${devicesToDelete.length - failed.length} of ${
|
|
559
|
-
devicesToDelete.length
|
|
560
|
-
} devices`
|
|
561
|
-
);
|
|
562
|
-
});
|
|
563
|
-
})
|
|
564
|
-
.then(() =>
|
|
565
|
-
targetCount !== undefined
|
|
566
|
-
? this._waitForDeviceCountBelowLimit(targetCount, 0)
|
|
567
|
-
: Promise.resolve()
|
|
568
|
-
)
|
|
569
|
-
.then(() => {
|
|
570
|
-
this.logger.info('device: device count confirmed below limit, cleanup successful');
|
|
493
|
+
return Promise.resolve();
|
|
571
494
|
})
|
|
572
495
|
.catch((error) => {
|
|
573
|
-
this.logger.error('
|
|
496
|
+
this.logger.error('Failed to retrieve devices:', error);
|
|
574
497
|
|
|
575
498
|
return Promise.reject(error);
|
|
576
499
|
});
|
|
@@ -596,11 +519,7 @@ const Device = WebexPlugin.extend({
|
|
|
596
519
|
|
|
597
520
|
return this._registerInternal(deviceRegistrationOptions).catch((error) => {
|
|
598
521
|
if (error?.body?.message === 'User has excessive device registrations') {
|
|
599
|
-
this.logger.info('device: excessive device registrations detected, initiating cleanup');
|
|
600
|
-
|
|
601
522
|
return this.deleteDevices().then(() => {
|
|
602
|
-
this.logger.info('device: device cleanup complete, retrying registration');
|
|
603
|
-
|
|
604
523
|
return this._registerInternal(deviceRegistrationOptions);
|
|
605
524
|
});
|
|
606
525
|
}
|
|
@@ -867,34 +786,6 @@ const Device = WebexPlugin.extend({
|
|
|
867
786
|
return Promise.reject(new Error('device: failed to get the current websocket url'));
|
|
868
787
|
},
|
|
869
788
|
|
|
870
|
-
/**
|
|
871
|
-
* Get sanitized processed debug features from session storage
|
|
872
|
-
* these should be JSON encoded and in the form {feature1: true, feature2: false}
|
|
873
|
-
*
|
|
874
|
-
* @returns {Array<Object>} - Array of sanitized debug feature toggles
|
|
875
|
-
*/
|
|
876
|
-
getDebugFeatures() {
|
|
877
|
-
const sanitizedDebugFeatures = [];
|
|
878
|
-
if (this.config.debugFeatureTogglesKey) {
|
|
879
|
-
const debugFeaturesString = this.webex
|
|
880
|
-
.getWindow()
|
|
881
|
-
.sessionStorage.getItem(this.config.debugFeatureTogglesKey);
|
|
882
|
-
if (debugFeaturesString) {
|
|
883
|
-
const debugFeatures = JSON.parse(debugFeaturesString);
|
|
884
|
-
Object.entries(debugFeatures).forEach(([key, value]) => {
|
|
885
|
-
sanitizedDebugFeatures.push({
|
|
886
|
-
key,
|
|
887
|
-
val: value ? 'true' : 'false',
|
|
888
|
-
mutable: true,
|
|
889
|
-
lastModified: new Date().toISOString(),
|
|
890
|
-
});
|
|
891
|
-
});
|
|
892
|
-
}
|
|
893
|
-
}
|
|
894
|
-
|
|
895
|
-
return sanitizedDebugFeatures;
|
|
896
|
-
},
|
|
897
|
-
|
|
898
789
|
/**
|
|
899
790
|
* Process a successful device registration.
|
|
900
791
|
*
|
|
@@ -923,14 +814,6 @@ const Device = WebexPlugin.extend({
|
|
|
923
814
|
// When using the etag feature cache, user and entitlement features are still returned
|
|
924
815
|
this.features.user.reset(features.user);
|
|
925
816
|
this.features.entitlement.reset(features.entitlement);
|
|
926
|
-
} else if (this.config.debugFeatureTogglesKey && body?.features?.developer) {
|
|
927
|
-
// Add the debug feature toggles from session storage if available
|
|
928
|
-
try {
|
|
929
|
-
const debugFeatures = this.getDebugFeatures();
|
|
930
|
-
body.features.developer.push(...debugFeatures);
|
|
931
|
-
} catch (error) {
|
|
932
|
-
this.logger.error('Failed to parse debug feature toggles from session storage:', error);
|
|
933
|
-
}
|
|
934
817
|
}
|
|
935
818
|
|
|
936
819
|
// Assign the recieved DTO from **WDM** to this device.
|
|
@@ -1063,13 +946,6 @@ const Device = WebexPlugin.extend({
|
|
|
1063
946
|
// Prototype the extended class in order to preserve the parent member.
|
|
1064
947
|
Reflect.apply(WebexPlugin.prototype.initialize, this, args);
|
|
1065
948
|
|
|
1066
|
-
this.listenToOnce(this.webex, 'change:config', () => {
|
|
1067
|
-
// If debug feature toggles exist, clear the etag to ensure developer feature toggles are fetched
|
|
1068
|
-
if (this.getDebugFeatures(this.config.debugFeatureTogglesKey).length > 0) {
|
|
1069
|
-
this.set('etag', undefined);
|
|
1070
|
-
}
|
|
1071
|
-
});
|
|
1072
|
-
|
|
1073
949
|
// Initialize feature events and listeners.
|
|
1074
950
|
FEATURE_COLLECTION_NAMES.forEach((collectionName) => {
|
|
1075
951
|
this.features.on(`change:${collectionName}`, (model, value, options) => {
|