@webex/calling 3.8.0 → 3.8.1-next.10

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.
Files changed (180) hide show
  1. package/dist/CallHistory/CallHistory.js +100 -63
  2. package/dist/CallHistory/CallHistory.js.map +1 -1
  3. package/dist/CallHistory/CallHistory.test.js +115 -19
  4. package/dist/CallHistory/CallHistory.test.js.map +1 -1
  5. package/dist/CallHistory/constants.js +9 -1
  6. package/dist/CallHistory/constants.js.map +1 -1
  7. package/dist/CallSettings/CallSettings.js +46 -13
  8. package/dist/CallSettings/CallSettings.js.map +1 -1
  9. package/dist/CallSettings/UcmBackendConnector.js +62 -18
  10. package/dist/CallSettings/UcmBackendConnector.js.map +1 -1
  11. package/dist/CallSettings/UcmBackendConnector.test.js +70 -7
  12. package/dist/CallSettings/UcmBackendConnector.test.js.map +1 -1
  13. package/dist/CallSettings/WxCallBackendConnector.js +153 -103
  14. package/dist/CallSettings/WxCallBackendConnector.js.map +1 -1
  15. package/dist/CallSettings/WxCallBackendConnector.test.js +52 -15
  16. package/dist/CallSettings/WxCallBackendConnector.test.js.map +1 -1
  17. package/dist/CallSettings/constants.js +15 -1
  18. package/dist/CallSettings/constants.js.map +1 -1
  19. package/dist/CallingClient/CallingClient.js +220 -159
  20. package/dist/CallingClient/CallingClient.js.map +1 -1
  21. package/dist/CallingClient/CallingClient.test.js +58 -27
  22. package/dist/CallingClient/CallingClient.test.js.map +1 -1
  23. package/dist/CallingClient/calling/call.js +251 -189
  24. package/dist/CallingClient/calling/call.js.map +1 -1
  25. package/dist/CallingClient/calling/call.test.js +96 -41
  26. package/dist/CallingClient/calling/call.test.js.map +1 -1
  27. package/dist/CallingClient/calling/callManager.js +73 -48
  28. package/dist/CallingClient/calling/callManager.js.map +1 -1
  29. package/dist/CallingClient/calling/callManager.test.js +96 -37
  30. package/dist/CallingClient/calling/callManager.test.js.map +1 -1
  31. package/dist/CallingClient/constants.js +105 -3
  32. package/dist/CallingClient/constants.js.map +1 -1
  33. package/dist/CallingClient/line/index.js +47 -18
  34. package/dist/CallingClient/line/index.js.map +1 -1
  35. package/dist/CallingClient/line/line.test.js +6 -12
  36. package/dist/CallingClient/line/line.test.js.map +1 -1
  37. package/dist/CallingClient/registration/register.js +590 -522
  38. package/dist/CallingClient/registration/register.js.map +1 -1
  39. package/dist/CallingClient/registration/register.test.js +821 -394
  40. package/dist/CallingClient/registration/register.test.js.map +1 -1
  41. package/dist/CallingClient/registration/types.js.map +1 -1
  42. package/dist/CallingClient/registration/webWorker.js +115 -0
  43. package/dist/CallingClient/registration/webWorker.js.map +1 -0
  44. package/dist/CallingClient/registration/webWorker.test.js +256 -0
  45. package/dist/CallingClient/registration/webWorker.test.js.map +1 -0
  46. package/dist/CallingClient/registration/webWorkerStr.js +15 -0
  47. package/dist/CallingClient/registration/webWorkerStr.js.map +1 -0
  48. package/dist/Contacts/ContactsClient.js +156 -102
  49. package/dist/Contacts/ContactsClient.js.map +1 -1
  50. package/dist/Contacts/ContactsClient.test.js +197 -49
  51. package/dist/Contacts/ContactsClient.test.js.map +1 -1
  52. package/dist/Contacts/constants.js +11 -1
  53. package/dist/Contacts/constants.js.map +1 -1
  54. package/dist/Errors/types.js +2 -0
  55. package/dist/Errors/types.js.map +1 -1
  56. package/dist/Events/impl/index.js +1 -1
  57. package/dist/Events/impl/index.js.map +1 -1
  58. package/dist/Metrics/index.js +102 -41
  59. package/dist/Metrics/index.js.map +1 -1
  60. package/dist/Metrics/index.test.js +10 -4
  61. package/dist/Metrics/index.test.js.map +1 -1
  62. package/dist/Metrics/types.js +4 -1
  63. package/dist/Metrics/types.js.map +1 -1
  64. package/dist/SDKConnector/types.js.map +1 -1
  65. package/dist/Voicemail/BroadworksBackendConnector.js +154 -91
  66. package/dist/Voicemail/BroadworksBackendConnector.js.map +1 -1
  67. package/dist/Voicemail/BroadworksBackendConnector.test.js +99 -19
  68. package/dist/Voicemail/BroadworksBackendConnector.test.js.map +1 -1
  69. package/dist/Voicemail/UcmBackendConnector.js +105 -54
  70. package/dist/Voicemail/UcmBackendConnector.js.map +1 -1
  71. package/dist/Voicemail/UcmBackendConnector.test.js +127 -17
  72. package/dist/Voicemail/UcmBackendConnector.test.js.map +1 -1
  73. package/dist/Voicemail/Voicemail.js +198 -79
  74. package/dist/Voicemail/Voicemail.js.map +1 -1
  75. package/dist/Voicemail/Voicemail.test.js +188 -23
  76. package/dist/Voicemail/Voicemail.test.js.map +1 -1
  77. package/dist/Voicemail/WxCallBackendConnector.js +277 -161
  78. package/dist/Voicemail/WxCallBackendConnector.js.map +1 -1
  79. package/dist/Voicemail/WxCallBackendConnector.test.js +268 -10
  80. package/dist/Voicemail/WxCallBackendConnector.test.js.map +1 -1
  81. package/dist/Voicemail/constants.js +25 -1
  82. package/dist/Voicemail/constants.js.map +1 -1
  83. package/dist/Voicemail/types.js.map +1 -1
  84. package/dist/common/Utils.js +168 -104
  85. package/dist/common/Utils.js.map +1 -1
  86. package/dist/common/Utils.test.js +199 -35
  87. package/dist/common/Utils.test.js.map +1 -1
  88. package/dist/common/constants.js +2 -1
  89. package/dist/common/constants.js.map +1 -1
  90. package/dist/common/testUtil.js +3 -0
  91. package/dist/common/testUtil.js.map +1 -1
  92. package/dist/common/types.js +8 -1
  93. package/dist/common/types.js.map +1 -1
  94. package/dist/index.js +12 -0
  95. package/dist/index.js.map +1 -1
  96. package/dist/module/CallHistory/CallHistory.js +32 -13
  97. package/dist/module/CallHistory/constants.js +6 -0
  98. package/dist/module/CallSettings/CallSettings.js +36 -3
  99. package/dist/module/CallSettings/UcmBackendConnector.js +50 -5
  100. package/dist/module/CallSettings/WxCallBackendConnector.js +54 -18
  101. package/dist/module/CallSettings/constants.js +12 -0
  102. package/dist/module/CallingClient/CallingClient.js +54 -16
  103. package/dist/module/CallingClient/calling/call.js +172 -121
  104. package/dist/module/CallingClient/calling/callManager.js +51 -26
  105. package/dist/module/CallingClient/constants.js +102 -2
  106. package/dist/module/CallingClient/line/index.js +37 -8
  107. package/dist/module/CallingClient/registration/register.js +151 -112
  108. package/dist/module/CallingClient/registration/webWorker.js +59 -0
  109. package/dist/module/CallingClient/registration/webWorkerStr.js +93 -0
  110. package/dist/module/Contacts/ContactsClient.js +65 -21
  111. package/dist/module/Contacts/constants.js +10 -0
  112. package/dist/module/Errors/types.js +2 -0
  113. package/dist/module/Events/impl/index.js +1 -1
  114. package/dist/module/Metrics/index.js +57 -2
  115. package/dist/module/Metrics/types.js +3 -0
  116. package/dist/module/Voicemail/BroadworksBackendConnector.js +66 -17
  117. package/dist/module/Voicemail/UcmBackendConnector.js +51 -11
  118. package/dist/module/Voicemail/Voicemail.js +109 -9
  119. package/dist/module/Voicemail/WxCallBackendConnector.js +67 -18
  120. package/dist/module/Voicemail/constants.js +21 -0
  121. package/dist/module/common/Utils.js +51 -12
  122. package/dist/module/common/constants.js +1 -0
  123. package/dist/module/common/testUtil.js +3 -0
  124. package/dist/module/common/types.js +7 -0
  125. package/dist/module/index.js +1 -0
  126. package/dist/types/CallHistory/CallHistory.d.ts.map +1 -1
  127. package/dist/types/CallHistory/constants.d.ts +6 -0
  128. package/dist/types/CallHistory/constants.d.ts.map +1 -1
  129. package/dist/types/CallSettings/CallSettings.d.ts.map +1 -1
  130. package/dist/types/CallSettings/UcmBackendConnector.d.ts.map +1 -1
  131. package/dist/types/CallSettings/WxCallBackendConnector.d.ts.map +1 -1
  132. package/dist/types/CallSettings/constants.d.ts +12 -0
  133. package/dist/types/CallSettings/constants.d.ts.map +1 -1
  134. package/dist/types/CallingClient/CallingClient.d.ts +2 -3
  135. package/dist/types/CallingClient/CallingClient.d.ts.map +1 -1
  136. package/dist/types/CallingClient/calling/call.d.ts.map +1 -1
  137. package/dist/types/CallingClient/calling/callManager.d.ts.map +1 -1
  138. package/dist/types/CallingClient/constants.d.ts +102 -2
  139. package/dist/types/CallingClient/constants.d.ts.map +1 -1
  140. package/dist/types/CallingClient/line/index.d.ts.map +1 -1
  141. package/dist/types/CallingClient/registration/register.d.ts +4 -3
  142. package/dist/types/CallingClient/registration/register.d.ts.map +1 -1
  143. package/dist/types/CallingClient/registration/types.d.ts +1 -0
  144. package/dist/types/CallingClient/registration/types.d.ts.map +1 -1
  145. package/dist/types/CallingClient/registration/webWorker.d.ts +2 -0
  146. package/dist/types/CallingClient/registration/webWorker.d.ts.map +1 -0
  147. package/dist/types/CallingClient/registration/webWorkerStr.d.ts +3 -0
  148. package/dist/types/CallingClient/registration/webWorkerStr.d.ts.map +1 -0
  149. package/dist/types/Contacts/ContactsClient.d.ts.map +1 -1
  150. package/dist/types/Contacts/constants.d.ts +10 -0
  151. package/dist/types/Contacts/constants.d.ts.map +1 -1
  152. package/dist/types/Errors/types.d.ts +2 -0
  153. package/dist/types/Errors/types.d.ts.map +1 -1
  154. package/dist/types/Metrics/index.d.ts +1 -1
  155. package/dist/types/Metrics/index.d.ts.map +1 -1
  156. package/dist/types/Metrics/types.d.ts +7 -2
  157. package/dist/types/Metrics/types.d.ts.map +1 -1
  158. package/dist/types/SDKConnector/types.d.ts +11 -2
  159. package/dist/types/SDKConnector/types.d.ts.map +1 -1
  160. package/dist/types/Voicemail/BroadworksBackendConnector.d.ts.map +1 -1
  161. package/dist/types/Voicemail/UcmBackendConnector.d.ts.map +1 -1
  162. package/dist/types/Voicemail/Voicemail.d.ts +1 -1
  163. package/dist/types/Voicemail/Voicemail.d.ts.map +1 -1
  164. package/dist/types/Voicemail/WxCallBackendConnector.d.ts +3 -1
  165. package/dist/types/Voicemail/WxCallBackendConnector.d.ts.map +1 -1
  166. package/dist/types/Voicemail/constants.d.ts +21 -0
  167. package/dist/types/Voicemail/constants.d.ts.map +1 -1
  168. package/dist/types/Voicemail/types.d.ts +1 -1
  169. package/dist/types/Voicemail/types.d.ts.map +1 -1
  170. package/dist/types/common/Utils.d.ts +4 -4
  171. package/dist/types/common/Utils.d.ts.map +1 -1
  172. package/dist/types/common/constants.d.ts +1 -0
  173. package/dist/types/common/constants.d.ts.map +1 -1
  174. package/dist/types/common/testUtil.d.ts +3 -0
  175. package/dist/types/common/testUtil.d.ts.map +1 -1
  176. package/dist/types/common/types.d.ts +24 -0
  177. package/dist/types/common/types.d.ts.map +1 -1
  178. package/dist/types/index.d.ts +2 -0
  179. package/dist/types/index.d.ts.map +1 -1
  180. package/package.json +4 -3
@@ -1,13 +1,14 @@
1
1
  import { v4 as uuid } from 'uuid';
2
- import { ERROR_CODE } from '../../Errors/types';
3
- import { emitFinalFailure, handleRegistrationErrors } from '../../common';
4
- import { METRIC_EVENT, METRIC_TYPE, REG_ACTION } from '../../Metrics/types';
2
+ import { METHOD_START_MESSAGE } from '../../common/constants';
3
+ import { emitFinalFailure, handleRegistrationErrors, uploadLogs } from '../../common';
4
+ import webWorkerStr from './webWorkerStr';
5
+ import { METRIC_EVENT, METRIC_TYPE, REG_ACTION, } from '../../Metrics/types';
5
6
  import { getMetricManager } from '../../Metrics';
6
7
  import { getCallManager } from '../calling';
7
8
  import log from '../../Logger';
8
9
  import SDKConnector from '../../SDKConnector';
9
- import { ALLOWED_SERVICES, HTTP_METHODS, RegistrationStatus, ServiceIndicator, } from '../../common/types';
10
- import { CALLING_USER_AGENT, CISCO_DEVICE_URL, DEVICES_ENDPOINT_RESOURCE, SPARK_USER_AGENT, WEBEX_WEB_CLIENT, BASE_REG_RETRY_TIMER_VAL_IN_SEC, BASE_REG_TIMER_MFACTOR, SEC_TO_MSEC_MFACTOR, REG_RANDOM_T_FACTOR_UPPER_LIMIT, REG_TRY_BACKUP_TIMER_VAL_IN_SEC, MINUTES_TO_SEC_MFACTOR, FAILBACK_429_RETRY_UTIL, REG_FAILBACK_429_MAX_RETRIES, FAILBACK_UTIL, REGISTRATION_FILE, DEFAULT_REHOMING_INTERVAL_MIN, DEFAULT_REHOMING_INTERVAL_MAX, DEFAULT_KEEPALIVE_INTERVAL, REG_TRY_BACKUP_TIMER_VAL_FOR_CC_IN_SEC, } from '../constants';
10
+ import { ALLOWED_SERVICES, HTTP_METHODS, RegistrationStatus, ServiceIndicator, WorkerMessageType, } from '../../common/types';
11
+ import { CALLING_USER_AGENT, CISCO_DEVICE_URL, DEVICES_ENDPOINT_RESOURCE, SPARK_USER_AGENT, WEBEX_WEB_CLIENT, BASE_REG_RETRY_TIMER_VAL_IN_SEC, BASE_REG_TIMER_MFACTOR, SEC_TO_MSEC_MFACTOR, REG_RANDOM_T_FACTOR_UPPER_LIMIT, REG_TRY_BACKUP_TIMER_VAL_IN_SEC, MINUTES_TO_SEC_MFACTOR, REG_429_RETRY_UTIL, REG_FAILBACK_429_MAX_RETRIES, FAILBACK_UTIL, REGISTRATION_FILE, DEFAULT_REHOMING_INTERVAL_MIN, DEFAULT_REHOMING_INTERVAL_MAX, DEFAULT_KEEPALIVE_INTERVAL, REG_TRY_BACKUP_TIMER_VAL_FOR_CC_IN_SEC, FAILOVER_UTIL, REGISTER_UTIL, RETRY_TIMER_UPPER_LIMIT, KEEPALIVE_UTIL, REGISTRATION_UTIL, METHODS, } from '../constants';
11
12
  import { LINE_EVENTS } from '../line/types';
12
13
  export class Registration {
13
14
  sdkConnector;
@@ -18,7 +19,6 @@ export class Registration {
18
19
  registrationStatus;
19
20
  failbackTimer;
20
21
  activeMobiusUrl;
21
- keepaliveTimer;
22
22
  rehomingIntervalMin;
23
23
  rehomingIntervalMax;
24
24
  mutex;
@@ -33,6 +33,9 @@ export class Registration {
33
33
  jwe;
34
34
  isCCFlow = false;
35
35
  failoverImmediately = false;
36
+ retryAfter;
37
+ scheduled429Retry = false;
38
+ webWorker;
36
39
  constructor(webex, serviceData, mutex, lineEmitter, logLevel, jwe) {
37
40
  this.jwe = jwe;
38
41
  this.sdkConnector = SDKConnector;
@@ -59,25 +62,18 @@ export class Registration {
59
62
  return this.activeMobiusUrl;
60
63
  }
61
64
  setActiveMobiusUrl(url) {
62
- log.info(`ActiveMobiusUrl: ${url}`, { method: 'setActiveMobiusUrl', file: REGISTRATION_FILE });
65
+ log.info(`${METHOD_START_MESSAGE} with ${url}`, {
66
+ method: METHODS.UPDATE_ACTIVE_MOBIUS,
67
+ file: REGISTRATION_FILE,
68
+ });
63
69
  this.activeMobiusUrl = url;
64
70
  this.callManager.updateActiveMobius(url);
65
71
  }
66
72
  setMobiusServers(primaryMobiusUris, backupMobiusUris) {
73
+ log.log(METHOD_START_MESSAGE, { method: METHODS.SET_MOBIUS_SERVERS, file: REGISTRATION_FILE });
67
74
  this.primaryMobiusUris = primaryMobiusUris;
68
75
  this.backupMobiusUris = backupMobiusUris;
69
76
  }
70
- async postKeepAlive(url) {
71
- return this.webex.request({
72
- uri: `${url}/status`,
73
- method: HTTP_METHODS.POST,
74
- headers: {
75
- [CISCO_DEVICE_URL]: this.webex.internal.device.url,
76
- [SPARK_USER_AGENT]: CALLING_USER_AGENT,
77
- },
78
- service: ALLOWED_SERVICES.MOBIUS,
79
- });
80
- }
81
77
  async deleteRegistration(url, deviceId, deviceUrl) {
82
78
  let response;
83
79
  try {
@@ -92,7 +88,10 @@ export class Registration {
92
88
  });
93
89
  }
94
90
  catch (error) {
95
- log.warn(`Delete failed with Mobius`, {});
91
+ log.warn(`Delete failed with Mobius ${error}`, {
92
+ file: REGISTRATION_FILE,
93
+ method: METHODS.DEREGISTER,
94
+ });
96
95
  }
97
96
  this.setStatus(RegistrationStatus.INACTIVE);
98
97
  this.lineEmitter(LINE_EVENTS.UNREGISTERED);
@@ -122,21 +121,27 @@ export class Registration {
122
121
  }
123
122
  return abort;
124
123
  }
125
- async scheduleFailback429Retry() {
126
- if (this.failback429RetryAttempts >= REG_FAILBACK_429_MAX_RETRIES) {
127
- return;
124
+ async handle429Retry(retryAfter, caller) {
125
+ if (caller === FAILBACK_UTIL) {
126
+ if (this.failback429RetryAttempts >= REG_FAILBACK_429_MAX_RETRIES) {
127
+ return;
128
+ }
129
+ this.clearFailbackTimer();
130
+ this.failback429RetryAttempts += 1;
131
+ log.log(`Received 429 while rehoming, 429 retry count : ${this.failback429RetryAttempts}`, {
132
+ file: REGISTRATION_FILE,
133
+ method: REG_429_RETRY_UTIL,
134
+ });
135
+ const interval = this.getRegRetryInterval(this.failback429RetryAttempts);
136
+ this.startFailbackTimer(interval);
137
+ this.scheduled429Retry = true;
138
+ const abort = await this.restorePreviousRegistration(REG_429_RETRY_UTIL);
139
+ if (!abort && !this.isDeviceRegistered()) {
140
+ await this.restartRegistration(REG_429_RETRY_UTIL);
141
+ }
128
142
  }
129
- this.clearFailbackTimer();
130
- this.failback429RetryAttempts += 1;
131
- log.log(`Received 429 while rehoming, 429 retry count : ${this.failback429RetryAttempts}`, {
132
- file: REGISTRATION_FILE,
133
- method: FAILBACK_429_RETRY_UTIL,
134
- });
135
- const interval = this.getRegRetryInterval(this.failback429RetryAttempts);
136
- this.startFailbackTimer(interval);
137
- const abort = await this.restorePreviousRegistration(FAILBACK_429_RETRY_UTIL);
138
- if (!abort && !this.isDeviceRegistered()) {
139
- await this.restartRegistration(FAILBACK_429_RETRY_UTIL);
143
+ else {
144
+ this.retryAfter = retryAfter;
140
145
  }
141
146
  }
142
147
  getRegRetryInterval(attempt = 1) {
@@ -149,7 +154,7 @@ export class Registration {
149
154
  async startFailoverTimer(attempt = 1, timeElapsed = 0) {
150
155
  const loggerContext = {
151
156
  file: REGISTRATION_FILE,
152
- method: this.startFailoverTimer.name,
157
+ method: FAILOVER_UTIL,
153
158
  };
154
159
  let interval = this.getRegRetryInterval(attempt);
155
160
  const TIMER_THRESHOLD = this.isCCFlow
@@ -159,12 +164,18 @@ export class Registration {
159
164
  const excessVal = timeElapsed + interval - TIMER_THRESHOLD;
160
165
  interval -= excessVal;
161
166
  }
167
+ if (this.retryAfter != null && interval < this.retryAfter) {
168
+ this.failoverImmediately = this.retryAfter + timeElapsed > TIMER_THRESHOLD;
169
+ }
162
170
  let abort;
163
171
  if (interval > BASE_REG_RETRY_TIMER_VAL_IN_SEC && !this.failoverImmediately) {
164
172
  const scheduledTime = Math.floor(Date.now() / 1000);
173
+ if (this.retryAfter != null) {
174
+ interval = Math.max(interval, this.retryAfter);
175
+ }
165
176
  setTimeout(async () => {
166
177
  await this.mutex.runExclusive(async () => {
167
- abort = await this.attemptRegistrationWithServers(this.startFailoverTimer.name);
178
+ abort = await this.attemptRegistrationWithServers(FAILOVER_UTIL);
168
179
  const currentTime = Math.floor(Date.now() / 1000);
169
180
  if (!abort && !this.isDeviceRegistered()) {
170
181
  await this.startFailoverTimer(attempt + 1, timeElapsed + (currentTime - scheduledTime));
@@ -174,15 +185,19 @@ export class Registration {
174
185
  log.log(`Scheduled retry with primary in ${interval} seconds, number of attempts : ${attempt}`, loggerContext);
175
186
  }
176
187
  else if (this.backupMobiusUris.length) {
177
- log.log('Failing over to backup servers.', loggerContext);
188
+ log.info('Failing over to backup servers.', loggerContext);
178
189
  this.failoverImmediately = false;
179
- abort = await this.attemptRegistrationWithServers(this.startFailoverTimer.name, this.backupMobiusUris);
190
+ abort = await this.attemptRegistrationWithServers(FAILOVER_UTIL, this.backupMobiusUris);
180
191
  if (!abort && !this.isDeviceRegistered()) {
181
192
  interval = this.getRegRetryInterval();
193
+ if (this.retryAfter != null && this.retryAfter < RETRY_TIMER_UPPER_LIMIT) {
194
+ interval = interval < this.retryAfter ? this.retryAfter : interval;
195
+ }
182
196
  setTimeout(async () => {
183
197
  await this.mutex.runExclusive(async () => {
184
- abort = await this.attemptRegistrationWithServers(this.startFailoverTimer.name, this.backupMobiusUris);
198
+ abort = await this.attemptRegistrationWithServers(FAILOVER_UTIL, this.backupMobiusUris);
185
199
  if (!abort && !this.isDeviceRegistered()) {
200
+ await uploadLogs();
186
201
  emitFinalFailure((clientError) => {
187
202
  this.lineEmitter(LINE_EVENTS.ERROR, undefined, clientError);
188
203
  }, loggerContext);
@@ -193,6 +208,7 @@ export class Registration {
193
208
  }
194
209
  }
195
210
  else {
211
+ await uploadLogs();
196
212
  emitFinalFailure((clientError) => {
197
213
  this.lineEmitter(LINE_EVENTS.ERROR, undefined, clientError);
198
214
  }, loggerContext);
@@ -241,19 +257,20 @@ export class Registration {
241
257
  });
242
258
  await this.deregister();
243
259
  const abort = await this.attemptRegistrationWithServers(FAILBACK_UTIL);
244
- if (!abort && !this.isDeviceRegistered()) {
245
- const abortNew = await this.restorePreviousRegistration(FAILBACK_UTIL);
246
- if (abortNew) {
247
- this.clearFailbackTimer();
248
- return;
249
- }
250
- if (!this.isDeviceRegistered()) {
251
- await this.restartRegistration(this.executeFailback.name);
252
- }
253
- else {
254
- this.failbackTimer = undefined;
255
- this.initiateFailback();
256
- }
260
+ if (this.scheduled429Retry || abort || this.isDeviceRegistered()) {
261
+ return;
262
+ }
263
+ const abortNew = await this.restorePreviousRegistration(FAILBACK_UTIL);
264
+ if (abortNew) {
265
+ this.clearFailbackTimer();
266
+ return;
267
+ }
268
+ if (!this.isDeviceRegistered()) {
269
+ await this.restartRegistration(this.executeFailback.name);
270
+ }
271
+ else {
272
+ this.failbackTimer = undefined;
273
+ this.initiateFailback();
257
274
  }
258
275
  }
259
276
  else {
@@ -298,9 +315,13 @@ export class Registration {
298
315
  }
299
316
  }
300
317
  async handleConnectionRestoration(retry) {
318
+ log.info(METHOD_START_MESSAGE, {
319
+ method: METHODS.HANDLE_CONNECTION_RESTORATION,
320
+ file: REGISTRATION_FILE,
321
+ });
301
322
  await this.mutex.runExclusive(async () => {
302
323
  if (retry) {
303
- log.info('Mercury connection is up again, re-registering with Webex Calling if needed', {
324
+ log.log('Mercury connection is up again, re-registering with Webex Calling if needed', {
304
325
  file: REGISTRATION_FILE,
305
326
  method: this.handleConnectionRestoration.name,
306
327
  });
@@ -345,7 +366,7 @@ export class Registration {
345
366
  }
346
367
  async triggerRegistration() {
347
368
  if (this.primaryMobiusUris.length > 0) {
348
- const abort = await this.attemptRegistrationWithServers(this.triggerRegistration.name, this.primaryMobiusUris);
369
+ const abort = await this.attemptRegistrationWithServers(REGISTRATION_UTIL, this.primaryMobiusUris);
349
370
  if (!this.isDeviceRegistered() && !abort) {
350
371
  await this.startFailoverTimer();
351
372
  }
@@ -353,34 +374,42 @@ export class Registration {
353
374
  }
354
375
  async attemptRegistrationWithServers(caller, servers = this.primaryMobiusUris) {
355
376
  let abort = false;
377
+ this.retryAfter = undefined;
356
378
  if (this.failoverImmediately) {
357
379
  return abort;
358
380
  }
359
381
  if (this.isDeviceRegistered()) {
360
- log.log(`[${caller}] : Device already registered with : ${this.activeMobiusUrl}`, {
382
+ log.info(`[${caller}] : Device already registered with : ${this.activeMobiusUrl}`, {
361
383
  file: REGISTRATION_FILE,
362
- method: this.attemptRegistrationWithServers.name,
384
+ method: REGISTER_UTIL,
363
385
  });
364
386
  return abort;
365
387
  }
366
388
  for (const url of servers) {
389
+ const serverType = (this.primaryMobiusUris.includes(url) && 'PRIMARY') ||
390
+ (this.backupMobiusUris?.includes(url) && 'BACKUP') ||
391
+ 'UNKNOWN';
367
392
  try {
368
393
  abort = false;
369
394
  this.registrationStatus = RegistrationStatus.INACTIVE;
370
395
  this.lineEmitter(LINE_EVENTS.CONNECTING);
371
- log.log(`[${caller}] : Mobius url to contact: ${url}`, {
396
+ log.info(`[${caller}] : Mobius url to contact: ${url}`, {
372
397
  file: REGISTRATION_FILE,
373
- method: this.attemptRegistrationWithServers.name,
398
+ method: REGISTER_UTIL,
374
399
  });
375
400
  const resp = await this.postRegistration(url);
376
401
  this.deviceInfo = resp.body;
377
402
  this.registrationStatus = RegistrationStatus.ACTIVE;
378
403
  this.lineEmitter(LINE_EVENTS.REGISTERED, resp.body);
404
+ log.log(`Registration successful for deviceId: ${this.deviceInfo.device?.deviceId} userId: ${this.userId}`, {
405
+ file: REGISTRATION_FILE,
406
+ method: METHODS.REGISTER,
407
+ });
379
408
  this.setActiveMobiusUrl(url);
380
409
  this.setIntervalValues(this.deviceInfo);
381
410
  this.metricManager.setDeviceInfo(this.deviceInfo);
382
- this.metricManager.submitRegistrationMetric(METRIC_EVENT.REGISTRATION, REG_ACTION.REGISTER, METRIC_TYPE.BEHAVIORAL, undefined);
383
- this.startKeepaliveTimer(this.deviceInfo.device?.uri, this.deviceInfo.keepaliveInterval);
411
+ this.metricManager.submitRegistrationMetric(METRIC_EVENT.REGISTRATION, REG_ACTION.REGISTER, METRIC_TYPE.BEHAVIORAL, caller, serverType, resp.headers?.trackingid ?? '', undefined, undefined);
412
+ this.startKeepaliveTimer(this.deviceInfo.device?.uri, this.deviceInfo.keepaliveInterval, serverType);
384
413
  this.initiateFailback();
385
414
  break;
386
415
  }
@@ -393,8 +422,8 @@ export class Registration {
393
422
  else {
394
423
  this.lineEmitter(LINE_EVENTS.UNREGISTERED);
395
424
  }
396
- this.metricManager.submitRegistrationMetric(METRIC_EVENT.REGISTRATION_ERROR, REG_ACTION.REGISTER, METRIC_TYPE.BEHAVIORAL, clientError);
397
- }, { method: this.attemptRegistrationWithServers.name, file: REGISTRATION_FILE }, this.restoreRegistrationCallBack());
425
+ this.metricManager.submitRegistrationMetric(METRIC_EVENT.REGISTRATION_ERROR, REG_ACTION.REGISTER, METRIC_TYPE.BEHAVIORAL, caller, serverType, body.headers?.trackingid ?? '', undefined, clientError);
426
+ }, { method: caller, file: REGISTRATION_FILE }, (retryAfter, retryCaller) => this.handle429Retry(retryAfter, retryCaller), this.restoreRegistrationCallBack());
398
427
  if (this.registrationStatus === RegistrationStatus.ACTIVE) {
399
428
  log.info(`[${caller}] : Device is already restored, active mobius url: ${this.activeMobiusUrl}`, {
400
429
  file: REGISTRATION_FILE,
@@ -406,69 +435,71 @@ export class Registration {
406
435
  this.setStatus(RegistrationStatus.INACTIVE);
407
436
  break;
408
437
  }
409
- else if (caller === this.executeFailback.name) {
410
- const error = body.statusCode;
411
- if (error === ERROR_CODE.TOO_MANY_REQUESTS) {
412
- await this.scheduleFailback429Retry();
413
- abort = true;
414
- break;
415
- }
416
- }
417
438
  }
418
439
  }
419
440
  return abort;
420
441
  }
421
- startKeepaliveTimer(url, interval) {
422
- let keepAliveRetryCount = 0;
442
+ async startKeepaliveTimer(url, interval, serverType) {
423
443
  this.clearKeepaliveTimer();
424
444
  const RETRY_COUNT_THRESHOLD = this.isCCFlow ? 4 : 5;
425
- this.keepaliveTimer = setInterval(async () => {
426
- const logContext = {
427
- file: REGISTRATION_FILE,
428
- method: this.startKeepaliveTimer.name,
429
- };
430
- await this.mutex.runExclusive(async () => {
431
- if (this.isDeviceRegistered() && keepAliveRetryCount < RETRY_COUNT_THRESHOLD) {
432
- try {
433
- const res = await this.postKeepAlive(url);
434
- log.info(`Sent Keepalive, status: ${res.statusCode}`, logContext);
435
- if (keepAliveRetryCount > 0) {
445
+ await this.mutex.runExclusive(async () => {
446
+ if (this.isDeviceRegistered()) {
447
+ const accessToken = await this.webex.credentials.getUserToken();
448
+ if (!this.webWorker) {
449
+ const blob = new Blob([webWorkerStr], { type: 'application/javascript' });
450
+ const blobUrl = URL.createObjectURL(blob);
451
+ this.webWorker = new Worker(blobUrl);
452
+ URL.revokeObjectURL(blobUrl);
453
+ this.webWorker.postMessage({
454
+ type: WorkerMessageType.START_KEEPALIVE,
455
+ accessToken: String(accessToken),
456
+ deviceUrl: String(this.webex.internal.device.url),
457
+ interval,
458
+ retryCountThreshold: RETRY_COUNT_THRESHOLD,
459
+ url,
460
+ });
461
+ this.webWorker.onmessage = async (event) => {
462
+ const logContext = {
463
+ file: REGISTRATION_FILE,
464
+ method: this.startKeepaliveTimer.name,
465
+ };
466
+ if (event.data.type === WorkerMessageType.KEEPALIVE_SUCCESS) {
467
+ log.info(`Sent Keepalive, status: ${event.data.statusCode}`, logContext);
436
468
  this.lineEmitter(LINE_EVENTS.RECONNECTED);
437
469
  }
438
- keepAliveRetryCount = 0;
439
- }
440
- catch (err) {
441
- keepAliveRetryCount += 1;
442
- const error = err;
443
- log.warn(`Keep-alive missed ${keepAliveRetryCount} times. Status -> ${error.statusCode} `, logContext);
444
- const abort = await handleRegistrationErrors(error, (clientError, finalError) => {
445
- if (finalError) {
446
- this.lineEmitter(LINE_EVENTS.ERROR, undefined, clientError);
470
+ if (event.data.type === WorkerMessageType.KEEPALIVE_FAILURE) {
471
+ const error = event.data.err;
472
+ log.warn(`Keep-alive missed ${event.data.keepAliveRetryCount} times. Status -> ${error.statusCode} `, logContext);
473
+ const abort = await handleRegistrationErrors(error, (clientError, finalError) => {
474
+ if (finalError) {
475
+ this.lineEmitter(LINE_EVENTS.ERROR, undefined, clientError);
476
+ }
477
+ this.metricManager.submitRegistrationMetric(METRIC_EVENT.REGISTRATION, REG_ACTION.KEEPALIVE_FAILURE, METRIC_TYPE.BEHAVIORAL, KEEPALIVE_UTIL, serverType, error.headers?.trackingid ?? '', event.data.keepAliveRetryCount, clientError);
478
+ }, { method: KEEPALIVE_UTIL, file: REGISTRATION_FILE });
479
+ if (abort || event.data.keepAliveRetryCount >= RETRY_COUNT_THRESHOLD) {
480
+ this.failoverImmediately = this.isCCFlow;
481
+ this.setStatus(RegistrationStatus.INACTIVE);
482
+ this.clearKeepaliveTimer();
483
+ this.clearFailbackTimer();
484
+ this.lineEmitter(LINE_EVENTS.UNREGISTERED);
485
+ if (!abort) {
486
+ await this.reconnectOnFailure(KEEPALIVE_UTIL);
487
+ }
447
488
  }
448
- this.metricManager.submitRegistrationMetric(METRIC_EVENT.REGISTRATION, REG_ACTION.KEEPALIVE_FAILURE, METRIC_TYPE.BEHAVIORAL, clientError);
449
- }, { method: this.startKeepaliveTimer.name, file: REGISTRATION_FILE });
450
- if (abort || keepAliveRetryCount >= RETRY_COUNT_THRESHOLD) {
451
- this.failoverImmediately = this.isCCFlow;
452
- this.setStatus(RegistrationStatus.INACTIVE);
453
- this.clearKeepaliveTimer();
454
- this.clearFailbackTimer();
455
- this.lineEmitter(LINE_EVENTS.UNREGISTERED);
456
- if (!abort) {
457
- await this.reconnectOnFailure(this.startKeepaliveTimer.name);
489
+ else {
490
+ this.lineEmitter(LINE_EVENTS.RECONNECTING);
458
491
  }
459
492
  }
460
- else {
461
- this.lineEmitter(LINE_EVENTS.RECONNECTING);
462
- }
463
- }
493
+ };
464
494
  }
465
- });
466
- }, interval * 1000);
495
+ }
496
+ });
467
497
  }
468
498
  clearKeepaliveTimer() {
469
- if (this.keepaliveTimer) {
470
- clearInterval(this.keepaliveTimer);
471
- this.keepaliveTimer = undefined;
499
+ if (this.webWorker) {
500
+ this.webWorker.postMessage({ type: WorkerMessageType.CLEAR_KEEPALIVE });
501
+ this.webWorker.terminate();
502
+ this.webWorker = undefined;
472
503
  }
473
504
  }
474
505
  isReconnectPending() {
@@ -477,9 +508,16 @@ export class Registration {
477
508
  async deregister() {
478
509
  try {
479
510
  await this.deleteRegistration(this.activeMobiusUrl, this.deviceInfo.device?.deviceId, this.deviceInfo.device?.clientDeviceUri);
511
+ log.log('Registration successfully deregistered', {
512
+ file: REGISTRATION_FILE,
513
+ method: METHODS.DEREGISTER,
514
+ });
480
515
  }
481
516
  catch (err) {
482
- log.warn(`Delete failed with Mobius`, {});
517
+ log.warn(`Delete failed with Mobius: ${err}`, {
518
+ file: REGISTRATION_FILE,
519
+ method: METHODS.DEREGISTER,
520
+ });
483
521
  }
484
522
  this.clearKeepaliveTimer();
485
523
  this.setStatus(RegistrationStatus.INACTIVE);
@@ -508,6 +546,7 @@ export class Registration {
508
546
  return false;
509
547
  }
510
548
  async reconnectOnFailure(caller) {
549
+ log.info(METHOD_START_MESSAGE, { method: METHODS.RECONNECT_ON_FAILURE, file: REGISTRATION_FILE });
511
550
  this.reconnectPending = false;
512
551
  if (!this.isDeviceRegistered()) {
513
552
  if (Object.keys(this.callManager.getActiveCalls()).length === 0) {
@@ -520,7 +559,7 @@ export class Registration {
520
559
  this.reconnectPending = true;
521
560
  log.info('Active call(s) present, deferred reconnect till call cleanup.', {
522
561
  file: REGISTRATION_FILE,
523
- method: this.reconnectOnFailure.name,
562
+ method: METHODS.RECONNECT_ON_FAILURE,
524
563
  });
525
564
  }
526
565
  }
@@ -0,0 +1,59 @@
1
+ import { v4 as uuid } from 'uuid';
2
+ import { HTTP_METHODS, WorkerMessageType } from '../../common/types';
3
+ let keepaliveTimer;
4
+ export const messageHandler = (event) => {
5
+ const { type } = event.data;
6
+ const postKeepAlive = async (accessToken, deviceUrl, url) => {
7
+ const response = await fetch(`${url}/status`, {
8
+ method: HTTP_METHODS.POST,
9
+ headers: {
10
+ 'cisco-device-url': deviceUrl,
11
+ 'spark-user-agent': 'webex-calling/beta',
12
+ Authorization: `${accessToken}`,
13
+ trackingId: `web_worker_${uuid()}`,
14
+ },
15
+ });
16
+ if (!response.ok) {
17
+ throw new Error(`Keepalive failed with status: ${response.status}`);
18
+ }
19
+ return response;
20
+ };
21
+ if (type === WorkerMessageType.START_KEEPALIVE) {
22
+ let keepAliveRetryCount = 0;
23
+ const { accessToken, deviceUrl, interval, retryCountThreshold, url } = event.data;
24
+ if (keepaliveTimer) {
25
+ clearInterval(keepaliveTimer);
26
+ keepaliveTimer = undefined;
27
+ }
28
+ keepaliveTimer = setInterval(async () => {
29
+ if (keepAliveRetryCount < retryCountThreshold) {
30
+ try {
31
+ const res = await postKeepAlive(accessToken, deviceUrl, url);
32
+ const statusCode = res.status;
33
+ if (keepAliveRetryCount > 0) {
34
+ postMessage({
35
+ type: WorkerMessageType.KEEPALIVE_SUCCESS,
36
+ statusCode,
37
+ });
38
+ }
39
+ keepAliveRetryCount = 0;
40
+ }
41
+ catch (err) {
42
+ keepAliveRetryCount += 1;
43
+ postMessage({
44
+ type: WorkerMessageType.KEEPALIVE_FAILURE,
45
+ err,
46
+ keepAliveRetryCount,
47
+ });
48
+ }
49
+ }
50
+ }, interval * 1000);
51
+ }
52
+ if (type === WorkerMessageType.CLEAR_KEEPALIVE) {
53
+ if (keepaliveTimer) {
54
+ clearInterval(keepaliveTimer);
55
+ keepaliveTimer = undefined;
56
+ }
57
+ }
58
+ };
59
+ self.addEventListener('message', messageHandler);
@@ -0,0 +1,93 @@
1
+ const webWorkerStr = `/* eslint-env worker */
2
+
3
+ const uuid = () => {
4
+ return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
5
+ const r = (Math.random() * 16) | 0;
6
+ const v = c === 'x' ? r : (r & 0x3) | 0x8;
7
+ return v.toString(16);
8
+ });
9
+ };
10
+
11
+ // Enum values from the original imports
12
+ const HTTP_METHODS = {
13
+ GET: 'GET',
14
+ POST: 'POST',
15
+ PUT: 'PUT',
16
+ DELETE: 'DELETE',
17
+ PATCH: 'PATCH',
18
+ };
19
+
20
+ const WorkerMessageType = {
21
+ START_KEEPALIVE: 'START_KEEPALIVE',
22
+ CLEAR_KEEPALIVE: 'CLEAR_KEEPALIVE',
23
+ KEEPALIVE_SUCCESS: 'KEEPALIVE_SUCCESS',
24
+ KEEPALIVE_FAILURE: 'KEEPALIVE_FAILURE',
25
+ };
26
+
27
+ let keepaliveTimer;
28
+
29
+ const messageHandler = (event) => {
30
+ const {type} = event.data;
31
+
32
+ const postKeepAlive = async (accessToken, deviceUrl, url) => {
33
+ const response = await fetch(\`\${url}/status\`, {
34
+ method: HTTP_METHODS.POST,
35
+ headers: {
36
+ 'cisco-device-url': deviceUrl,
37
+ 'spark-user-agent': 'webex-calling/beta',
38
+ Authorization: \`\${accessToken}\`,
39
+ trackingId: \`web_worker_\${uuid()}\`,
40
+ },
41
+ });
42
+
43
+ if (!response.ok) {
44
+ throw new Error(\`Keepalive failed with status: \${response.status}\`);
45
+ }
46
+
47
+ return response;
48
+ };
49
+
50
+ if (type === WorkerMessageType.START_KEEPALIVE) {
51
+ let keepAliveRetryCount = 0;
52
+ const {accessToken, deviceUrl, interval, retryCountThreshold, url} = event.data;
53
+
54
+ if (keepaliveTimer) {
55
+ clearInterval(keepaliveTimer);
56
+ keepaliveTimer = undefined;
57
+ }
58
+
59
+ keepaliveTimer = setInterval(async () => {
60
+ if (keepAliveRetryCount < retryCountThreshold) {
61
+ try {
62
+ const res = await postKeepAlive(accessToken, deviceUrl, url);
63
+ const statusCode = res.status;
64
+ if (keepAliveRetryCount > 0) {
65
+ self.postMessage({
66
+ type: WorkerMessageType.KEEPALIVE_SUCCESS,
67
+ statusCode,
68
+ });
69
+ }
70
+ keepAliveRetryCount = 0;
71
+ } catch (err) {
72
+ keepAliveRetryCount += 1;
73
+ self.postMessage({
74
+ type: WorkerMessageType.KEEPALIVE_FAILURE,
75
+ err,
76
+ keepAliveRetryCount,
77
+ });
78
+ }
79
+ }
80
+ }, interval * 1000);
81
+ }
82
+
83
+ if (type === WorkerMessageType.CLEAR_KEEPALIVE) {
84
+ if (keepaliveTimer) {
85
+ clearInterval(keepaliveTimer);
86
+ keepaliveTimer = undefined;
87
+ }
88
+ }
89
+ };
90
+
91
+ self.addEventListener('message', messageHandler);
92
+ `;
93
+ export default webWorkerStr;