@webex/calling 3.8.0 → 3.8.1-next.2

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 (166) 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 +53 -24
  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 +2 -2
  36. package/dist/CallingClient/line/line.test.js.map +1 -1
  37. package/dist/CallingClient/registration/register.js +359 -297
  38. package/dist/CallingClient/registration/register.js.map +1 -1
  39. package/dist/CallingClient/registration/register.test.js +561 -163
  40. package/dist/CallingClient/registration/register.test.js.map +1 -1
  41. package/dist/CallingClient/registration/types.js.map +1 -1
  42. package/dist/Contacts/ContactsClient.js +156 -102
  43. package/dist/Contacts/ContactsClient.js.map +1 -1
  44. package/dist/Contacts/ContactsClient.test.js +197 -49
  45. package/dist/Contacts/ContactsClient.test.js.map +1 -1
  46. package/dist/Contacts/constants.js +11 -1
  47. package/dist/Contacts/constants.js.map +1 -1
  48. package/dist/Errors/types.js +2 -0
  49. package/dist/Errors/types.js.map +1 -1
  50. package/dist/Events/impl/index.js +1 -1
  51. package/dist/Events/impl/index.js.map +1 -1
  52. package/dist/Metrics/index.js +102 -41
  53. package/dist/Metrics/index.js.map +1 -1
  54. package/dist/Metrics/index.test.js +10 -4
  55. package/dist/Metrics/index.test.js.map +1 -1
  56. package/dist/Metrics/types.js +4 -1
  57. package/dist/Metrics/types.js.map +1 -1
  58. package/dist/SDKConnector/types.js.map +1 -1
  59. package/dist/Voicemail/BroadworksBackendConnector.js +154 -91
  60. package/dist/Voicemail/BroadworksBackendConnector.js.map +1 -1
  61. package/dist/Voicemail/BroadworksBackendConnector.test.js +99 -19
  62. package/dist/Voicemail/BroadworksBackendConnector.test.js.map +1 -1
  63. package/dist/Voicemail/UcmBackendConnector.js +105 -54
  64. package/dist/Voicemail/UcmBackendConnector.js.map +1 -1
  65. package/dist/Voicemail/UcmBackendConnector.test.js +127 -17
  66. package/dist/Voicemail/UcmBackendConnector.test.js.map +1 -1
  67. package/dist/Voicemail/Voicemail.js +198 -79
  68. package/dist/Voicemail/Voicemail.js.map +1 -1
  69. package/dist/Voicemail/Voicemail.test.js +188 -23
  70. package/dist/Voicemail/Voicemail.test.js.map +1 -1
  71. package/dist/Voicemail/WxCallBackendConnector.js +277 -161
  72. package/dist/Voicemail/WxCallBackendConnector.js.map +1 -1
  73. package/dist/Voicemail/WxCallBackendConnector.test.js +268 -10
  74. package/dist/Voicemail/WxCallBackendConnector.test.js.map +1 -1
  75. package/dist/Voicemail/constants.js +25 -1
  76. package/dist/Voicemail/constants.js.map +1 -1
  77. package/dist/Voicemail/types.js.map +1 -1
  78. package/dist/common/Utils.js +168 -104
  79. package/dist/common/Utils.js.map +1 -1
  80. package/dist/common/Utils.test.js +199 -35
  81. package/dist/common/Utils.test.js.map +1 -1
  82. package/dist/common/constants.js +2 -1
  83. package/dist/common/constants.js.map +1 -1
  84. package/dist/common/testUtil.js +3 -0
  85. package/dist/common/testUtil.js.map +1 -1
  86. package/dist/common/types.js.map +1 -1
  87. package/dist/index.js +12 -0
  88. package/dist/index.js.map +1 -1
  89. package/dist/module/CallHistory/CallHistory.js +32 -13
  90. package/dist/module/CallHistory/constants.js +6 -0
  91. package/dist/module/CallSettings/CallSettings.js +36 -3
  92. package/dist/module/CallSettings/UcmBackendConnector.js +50 -5
  93. package/dist/module/CallSettings/WxCallBackendConnector.js +54 -18
  94. package/dist/module/CallSettings/constants.js +12 -0
  95. package/dist/module/CallingClient/CallingClient.js +54 -16
  96. package/dist/module/CallingClient/calling/call.js +172 -121
  97. package/dist/module/CallingClient/calling/callManager.js +51 -26
  98. package/dist/module/CallingClient/constants.js +102 -2
  99. package/dist/module/CallingClient/line/index.js +37 -8
  100. package/dist/module/CallingClient/registration/register.js +103 -64
  101. package/dist/module/Contacts/ContactsClient.js +65 -21
  102. package/dist/module/Contacts/constants.js +10 -0
  103. package/dist/module/Errors/types.js +2 -0
  104. package/dist/module/Events/impl/index.js +1 -1
  105. package/dist/module/Metrics/index.js +57 -2
  106. package/dist/module/Metrics/types.js +3 -0
  107. package/dist/module/Voicemail/BroadworksBackendConnector.js +66 -17
  108. package/dist/module/Voicemail/UcmBackendConnector.js +51 -11
  109. package/dist/module/Voicemail/Voicemail.js +109 -9
  110. package/dist/module/Voicemail/WxCallBackendConnector.js +67 -18
  111. package/dist/module/Voicemail/constants.js +21 -0
  112. package/dist/module/common/Utils.js +51 -12
  113. package/dist/module/common/constants.js +1 -0
  114. package/dist/module/common/testUtil.js +3 -0
  115. package/dist/module/index.js +1 -0
  116. package/dist/types/CallHistory/CallHistory.d.ts.map +1 -1
  117. package/dist/types/CallHistory/constants.d.ts +6 -0
  118. package/dist/types/CallHistory/constants.d.ts.map +1 -1
  119. package/dist/types/CallSettings/CallSettings.d.ts.map +1 -1
  120. package/dist/types/CallSettings/UcmBackendConnector.d.ts.map +1 -1
  121. package/dist/types/CallSettings/WxCallBackendConnector.d.ts.map +1 -1
  122. package/dist/types/CallSettings/constants.d.ts +12 -0
  123. package/dist/types/CallSettings/constants.d.ts.map +1 -1
  124. package/dist/types/CallingClient/CallingClient.d.ts +2 -3
  125. package/dist/types/CallingClient/CallingClient.d.ts.map +1 -1
  126. package/dist/types/CallingClient/calling/call.d.ts.map +1 -1
  127. package/dist/types/CallingClient/calling/callManager.d.ts.map +1 -1
  128. package/dist/types/CallingClient/constants.d.ts +102 -2
  129. package/dist/types/CallingClient/constants.d.ts.map +1 -1
  130. package/dist/types/CallingClient/line/index.d.ts.map +1 -1
  131. package/dist/types/CallingClient/registration/register.d.ts +3 -1
  132. package/dist/types/CallingClient/registration/register.d.ts.map +1 -1
  133. package/dist/types/CallingClient/registration/types.d.ts +1 -0
  134. package/dist/types/CallingClient/registration/types.d.ts.map +1 -1
  135. package/dist/types/Contacts/ContactsClient.d.ts.map +1 -1
  136. package/dist/types/Contacts/constants.d.ts +10 -0
  137. package/dist/types/Contacts/constants.d.ts.map +1 -1
  138. package/dist/types/Errors/types.d.ts +2 -0
  139. package/dist/types/Errors/types.d.ts.map +1 -1
  140. package/dist/types/Metrics/index.d.ts +1 -1
  141. package/dist/types/Metrics/index.d.ts.map +1 -1
  142. package/dist/types/Metrics/types.d.ts +7 -2
  143. package/dist/types/Metrics/types.d.ts.map +1 -1
  144. package/dist/types/SDKConnector/types.d.ts +11 -2
  145. package/dist/types/SDKConnector/types.d.ts.map +1 -1
  146. package/dist/types/Voicemail/BroadworksBackendConnector.d.ts.map +1 -1
  147. package/dist/types/Voicemail/UcmBackendConnector.d.ts.map +1 -1
  148. package/dist/types/Voicemail/Voicemail.d.ts +1 -1
  149. package/dist/types/Voicemail/Voicemail.d.ts.map +1 -1
  150. package/dist/types/Voicemail/WxCallBackendConnector.d.ts +3 -1
  151. package/dist/types/Voicemail/WxCallBackendConnector.d.ts.map +1 -1
  152. package/dist/types/Voicemail/constants.d.ts +21 -0
  153. package/dist/types/Voicemail/constants.d.ts.map +1 -1
  154. package/dist/types/Voicemail/types.d.ts +1 -1
  155. package/dist/types/Voicemail/types.d.ts.map +1 -1
  156. package/dist/types/common/Utils.d.ts +4 -4
  157. package/dist/types/common/Utils.d.ts.map +1 -1
  158. package/dist/types/common/constants.d.ts +1 -0
  159. package/dist/types/common/constants.d.ts.map +1 -1
  160. package/dist/types/common/testUtil.d.ts +3 -0
  161. package/dist/types/common/testUtil.d.ts.map +1 -1
  162. package/dist/types/common/types.d.ts +12 -0
  163. package/dist/types/common/types.d.ts.map +1 -1
  164. package/dist/types/index.d.ts +2 -0
  165. package/dist/types/index.d.ts.map +1 -1
  166. package/package.json +4 -3
@@ -1,13 +1,13 @@
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 { METRIC_EVENT, METRIC_TYPE, REG_ACTION, } from '../../Metrics/types';
5
5
  import { getMetricManager } from '../../Metrics';
6
6
  import { getCallManager } from '../calling';
7
7
  import log from '../../Logger';
8
8
  import SDKConnector from '../../SDKConnector';
9
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 { 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
11
  import { LINE_EVENTS } from '../line/types';
12
12
  export class Registration {
13
13
  sdkConnector;
@@ -33,6 +33,8 @@ export class Registration {
33
33
  jwe;
34
34
  isCCFlow = false;
35
35
  failoverImmediately = false;
36
+ retryAfter;
37
+ scheduled429Retry = false;
36
38
  constructor(webex, serviceData, mutex, lineEmitter, logLevel, jwe) {
37
39
  this.jwe = jwe;
38
40
  this.sdkConnector = SDKConnector;
@@ -59,11 +61,15 @@ export class Registration {
59
61
  return this.activeMobiusUrl;
60
62
  }
61
63
  setActiveMobiusUrl(url) {
62
- log.info(`ActiveMobiusUrl: ${url}`, { method: 'setActiveMobiusUrl', file: REGISTRATION_FILE });
64
+ log.info(`${METHOD_START_MESSAGE} with ${url}`, {
65
+ method: METHODS.UPDATE_ACTIVE_MOBIUS,
66
+ file: REGISTRATION_FILE,
67
+ });
63
68
  this.activeMobiusUrl = url;
64
69
  this.callManager.updateActiveMobius(url);
65
70
  }
66
71
  setMobiusServers(primaryMobiusUris, backupMobiusUris) {
72
+ log.log(METHOD_START_MESSAGE, { method: METHODS.SET_MOBIUS_SERVERS, file: REGISTRATION_FILE });
67
73
  this.primaryMobiusUris = primaryMobiusUris;
68
74
  this.backupMobiusUris = backupMobiusUris;
69
75
  }
@@ -92,7 +98,10 @@ export class Registration {
92
98
  });
93
99
  }
94
100
  catch (error) {
95
- log.warn(`Delete failed with Mobius`, {});
101
+ log.warn(`Delete failed with Mobius ${error}`, {
102
+ file: REGISTRATION_FILE,
103
+ method: METHODS.DEREGISTER,
104
+ });
96
105
  }
97
106
  this.setStatus(RegistrationStatus.INACTIVE);
98
107
  this.lineEmitter(LINE_EVENTS.UNREGISTERED);
@@ -122,21 +131,27 @@ export class Registration {
122
131
  }
123
132
  return abort;
124
133
  }
125
- async scheduleFailback429Retry() {
126
- if (this.failback429RetryAttempts >= REG_FAILBACK_429_MAX_RETRIES) {
127
- return;
134
+ async handle429Retry(retryAfter, caller) {
135
+ if (caller === FAILBACK_UTIL) {
136
+ if (this.failback429RetryAttempts >= REG_FAILBACK_429_MAX_RETRIES) {
137
+ return;
138
+ }
139
+ this.clearFailbackTimer();
140
+ this.failback429RetryAttempts += 1;
141
+ log.log(`Received 429 while rehoming, 429 retry count : ${this.failback429RetryAttempts}`, {
142
+ file: REGISTRATION_FILE,
143
+ method: REG_429_RETRY_UTIL,
144
+ });
145
+ const interval = this.getRegRetryInterval(this.failback429RetryAttempts);
146
+ this.startFailbackTimer(interval);
147
+ this.scheduled429Retry = true;
148
+ const abort = await this.restorePreviousRegistration(REG_429_RETRY_UTIL);
149
+ if (!abort && !this.isDeviceRegistered()) {
150
+ await this.restartRegistration(REG_429_RETRY_UTIL);
151
+ }
128
152
  }
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);
153
+ else {
154
+ this.retryAfter = retryAfter;
140
155
  }
141
156
  }
142
157
  getRegRetryInterval(attempt = 1) {
@@ -149,7 +164,7 @@ export class Registration {
149
164
  async startFailoverTimer(attempt = 1, timeElapsed = 0) {
150
165
  const loggerContext = {
151
166
  file: REGISTRATION_FILE,
152
- method: this.startFailoverTimer.name,
167
+ method: FAILOVER_UTIL,
153
168
  };
154
169
  let interval = this.getRegRetryInterval(attempt);
155
170
  const TIMER_THRESHOLD = this.isCCFlow
@@ -159,12 +174,18 @@ export class Registration {
159
174
  const excessVal = timeElapsed + interval - TIMER_THRESHOLD;
160
175
  interval -= excessVal;
161
176
  }
177
+ if (this.retryAfter != null && interval < this.retryAfter) {
178
+ this.failoverImmediately = this.retryAfter + timeElapsed > TIMER_THRESHOLD;
179
+ }
162
180
  let abort;
163
181
  if (interval > BASE_REG_RETRY_TIMER_VAL_IN_SEC && !this.failoverImmediately) {
164
182
  const scheduledTime = Math.floor(Date.now() / 1000);
183
+ if (this.retryAfter != null) {
184
+ interval = Math.max(interval, this.retryAfter);
185
+ }
165
186
  setTimeout(async () => {
166
187
  await this.mutex.runExclusive(async () => {
167
- abort = await this.attemptRegistrationWithServers(this.startFailoverTimer.name);
188
+ abort = await this.attemptRegistrationWithServers(FAILOVER_UTIL);
168
189
  const currentTime = Math.floor(Date.now() / 1000);
169
190
  if (!abort && !this.isDeviceRegistered()) {
170
191
  await this.startFailoverTimer(attempt + 1, timeElapsed + (currentTime - scheduledTime));
@@ -174,15 +195,19 @@ export class Registration {
174
195
  log.log(`Scheduled retry with primary in ${interval} seconds, number of attempts : ${attempt}`, loggerContext);
175
196
  }
176
197
  else if (this.backupMobiusUris.length) {
177
- log.log('Failing over to backup servers.', loggerContext);
198
+ log.info('Failing over to backup servers.', loggerContext);
178
199
  this.failoverImmediately = false;
179
- abort = await this.attemptRegistrationWithServers(this.startFailoverTimer.name, this.backupMobiusUris);
200
+ abort = await this.attemptRegistrationWithServers(FAILOVER_UTIL, this.backupMobiusUris);
180
201
  if (!abort && !this.isDeviceRegistered()) {
181
202
  interval = this.getRegRetryInterval();
203
+ if (this.retryAfter != null && this.retryAfter < RETRY_TIMER_UPPER_LIMIT) {
204
+ interval = interval < this.retryAfter ? this.retryAfter : interval;
205
+ }
182
206
  setTimeout(async () => {
183
207
  await this.mutex.runExclusive(async () => {
184
- abort = await this.attemptRegistrationWithServers(this.startFailoverTimer.name, this.backupMobiusUris);
208
+ abort = await this.attemptRegistrationWithServers(FAILOVER_UTIL, this.backupMobiusUris);
185
209
  if (!abort && !this.isDeviceRegistered()) {
210
+ await uploadLogs();
186
211
  emitFinalFailure((clientError) => {
187
212
  this.lineEmitter(LINE_EVENTS.ERROR, undefined, clientError);
188
213
  }, loggerContext);
@@ -193,6 +218,7 @@ export class Registration {
193
218
  }
194
219
  }
195
220
  else {
221
+ await uploadLogs();
196
222
  emitFinalFailure((clientError) => {
197
223
  this.lineEmitter(LINE_EVENTS.ERROR, undefined, clientError);
198
224
  }, loggerContext);
@@ -241,19 +267,20 @@ export class Registration {
241
267
  });
242
268
  await this.deregister();
243
269
  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
- }
270
+ if (this.scheduled429Retry || abort || this.isDeviceRegistered()) {
271
+ return;
272
+ }
273
+ const abortNew = await this.restorePreviousRegistration(FAILBACK_UTIL);
274
+ if (abortNew) {
275
+ this.clearFailbackTimer();
276
+ return;
277
+ }
278
+ if (!this.isDeviceRegistered()) {
279
+ await this.restartRegistration(this.executeFailback.name);
280
+ }
281
+ else {
282
+ this.failbackTimer = undefined;
283
+ this.initiateFailback();
257
284
  }
258
285
  }
259
286
  else {
@@ -298,9 +325,13 @@ export class Registration {
298
325
  }
299
326
  }
300
327
  async handleConnectionRestoration(retry) {
328
+ log.info(METHOD_START_MESSAGE, {
329
+ method: METHODS.HANDLE_CONNECTION_RESTORATION,
330
+ file: REGISTRATION_FILE,
331
+ });
301
332
  await this.mutex.runExclusive(async () => {
302
333
  if (retry) {
303
- log.info('Mercury connection is up again, re-registering with Webex Calling if needed', {
334
+ log.log('Mercury connection is up again, re-registering with Webex Calling if needed', {
304
335
  file: REGISTRATION_FILE,
305
336
  method: this.handleConnectionRestoration.name,
306
337
  });
@@ -345,7 +376,7 @@ export class Registration {
345
376
  }
346
377
  async triggerRegistration() {
347
378
  if (this.primaryMobiusUris.length > 0) {
348
- const abort = await this.attemptRegistrationWithServers(this.triggerRegistration.name, this.primaryMobiusUris);
379
+ const abort = await this.attemptRegistrationWithServers(REGISTRATION_UTIL, this.primaryMobiusUris);
349
380
  if (!this.isDeviceRegistered() && !abort) {
350
381
  await this.startFailoverTimer();
351
382
  }
@@ -353,34 +384,42 @@ export class Registration {
353
384
  }
354
385
  async attemptRegistrationWithServers(caller, servers = this.primaryMobiusUris) {
355
386
  let abort = false;
387
+ this.retryAfter = undefined;
356
388
  if (this.failoverImmediately) {
357
389
  return abort;
358
390
  }
359
391
  if (this.isDeviceRegistered()) {
360
- log.log(`[${caller}] : Device already registered with : ${this.activeMobiusUrl}`, {
392
+ log.info(`[${caller}] : Device already registered with : ${this.activeMobiusUrl}`, {
361
393
  file: REGISTRATION_FILE,
362
- method: this.attemptRegistrationWithServers.name,
394
+ method: REGISTER_UTIL,
363
395
  });
364
396
  return abort;
365
397
  }
366
398
  for (const url of servers) {
399
+ const serverType = (this.primaryMobiusUris.includes(url) && 'PRIMARY') ||
400
+ (this.backupMobiusUris?.includes(url) && 'BACKUP') ||
401
+ 'UNKNOWN';
367
402
  try {
368
403
  abort = false;
369
404
  this.registrationStatus = RegistrationStatus.INACTIVE;
370
405
  this.lineEmitter(LINE_EVENTS.CONNECTING);
371
- log.log(`[${caller}] : Mobius url to contact: ${url}`, {
406
+ log.info(`[${caller}] : Mobius url to contact: ${url}`, {
372
407
  file: REGISTRATION_FILE,
373
- method: this.attemptRegistrationWithServers.name,
408
+ method: REGISTER_UTIL,
374
409
  });
375
410
  const resp = await this.postRegistration(url);
376
411
  this.deviceInfo = resp.body;
377
412
  this.registrationStatus = RegistrationStatus.ACTIVE;
378
413
  this.lineEmitter(LINE_EVENTS.REGISTERED, resp.body);
414
+ log.log(`Registration successful for deviceId: ${this.deviceInfo.device?.deviceId} userId: ${this.userId}`, {
415
+ file: REGISTRATION_FILE,
416
+ method: METHODS.REGISTER,
417
+ });
379
418
  this.setActiveMobiusUrl(url);
380
419
  this.setIntervalValues(this.deviceInfo);
381
420
  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);
421
+ this.metricManager.submitRegistrationMetric(METRIC_EVENT.REGISTRATION, REG_ACTION.REGISTER, METRIC_TYPE.BEHAVIORAL, caller, serverType, resp.headers?.trackingid ?? '', undefined, undefined);
422
+ this.startKeepaliveTimer(this.deviceInfo.device?.uri, this.deviceInfo.keepaliveInterval, serverType);
384
423
  this.initiateFailback();
385
424
  break;
386
425
  }
@@ -393,8 +432,8 @@ export class Registration {
393
432
  else {
394
433
  this.lineEmitter(LINE_EVENTS.UNREGISTERED);
395
434
  }
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());
435
+ this.metricManager.submitRegistrationMetric(METRIC_EVENT.REGISTRATION_ERROR, REG_ACTION.REGISTER, METRIC_TYPE.BEHAVIORAL, caller, serverType, body.headers?.trackingid ?? '', undefined, clientError);
436
+ }, { method: caller, file: REGISTRATION_FILE }, (retryAfter, retryCaller) => this.handle429Retry(retryAfter, retryCaller), this.restoreRegistrationCallBack());
398
437
  if (this.registrationStatus === RegistrationStatus.ACTIVE) {
399
438
  log.info(`[${caller}] : Device is already restored, active mobius url: ${this.activeMobiusUrl}`, {
400
439
  file: REGISTRATION_FILE,
@@ -406,32 +445,24 @@ export class Registration {
406
445
  this.setStatus(RegistrationStatus.INACTIVE);
407
446
  break;
408
447
  }
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
448
  }
418
449
  }
419
450
  return abort;
420
451
  }
421
- startKeepaliveTimer(url, interval) {
452
+ startKeepaliveTimer(url, interval, serverType) {
422
453
  let keepAliveRetryCount = 0;
423
454
  this.clearKeepaliveTimer();
424
455
  const RETRY_COUNT_THRESHOLD = this.isCCFlow ? 4 : 5;
425
456
  this.keepaliveTimer = setInterval(async () => {
426
457
  const logContext = {
427
458
  file: REGISTRATION_FILE,
428
- method: this.startKeepaliveTimer.name,
459
+ method: KEEPALIVE_UTIL,
429
460
  };
430
461
  await this.mutex.runExclusive(async () => {
431
462
  if (this.isDeviceRegistered() && keepAliveRetryCount < RETRY_COUNT_THRESHOLD) {
432
463
  try {
433
464
  const res = await this.postKeepAlive(url);
434
- log.info(`Sent Keepalive, status: ${res.statusCode}`, logContext);
465
+ log.log(`Sent Keepalive, status: ${res.statusCode}`, logContext);
435
466
  if (keepAliveRetryCount > 0) {
436
467
  this.lineEmitter(LINE_EVENTS.RECONNECTED);
437
468
  }
@@ -445,8 +476,8 @@ export class Registration {
445
476
  if (finalError) {
446
477
  this.lineEmitter(LINE_EVENTS.ERROR, undefined, clientError);
447
478
  }
448
- this.metricManager.submitRegistrationMetric(METRIC_EVENT.REGISTRATION, REG_ACTION.KEEPALIVE_FAILURE, METRIC_TYPE.BEHAVIORAL, clientError);
449
- }, { method: this.startKeepaliveTimer.name, file: REGISTRATION_FILE });
479
+ this.metricManager.submitRegistrationMetric(METRIC_EVENT.REGISTRATION, REG_ACTION.KEEPALIVE_FAILURE, METRIC_TYPE.BEHAVIORAL, KEEPALIVE_UTIL, serverType, error.headers?.trackingid ?? '', keepAliveRetryCount, clientError);
480
+ }, { method: KEEPALIVE_UTIL, file: REGISTRATION_FILE });
450
481
  if (abort || keepAliveRetryCount >= RETRY_COUNT_THRESHOLD) {
451
482
  this.failoverImmediately = this.isCCFlow;
452
483
  this.setStatus(RegistrationStatus.INACTIVE);
@@ -454,7 +485,7 @@ export class Registration {
454
485
  this.clearFailbackTimer();
455
486
  this.lineEmitter(LINE_EVENTS.UNREGISTERED);
456
487
  if (!abort) {
457
- await this.reconnectOnFailure(this.startKeepaliveTimer.name);
488
+ await this.reconnectOnFailure(KEEPALIVE_UTIL);
458
489
  }
459
490
  }
460
491
  else {
@@ -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
  }
@@ -1,10 +1,10 @@
1
- import { FAILURE_MESSAGE, SCIM_ENTERPRISE_USER, SCIM_WEBEXIDENTITY_USER, STATUS_CODE, SUCCESS_MESSAGE, } from '../common/constants';
1
+ import { FAILURE_MESSAGE, METHOD_START_MESSAGE, SCIM_ENTERPRISE_USER, SCIM_WEBEXIDENTITY_USER, STATUS_CODE, SUCCESS_MESSAGE, } from '../common/constants';
2
2
  import { HTTP_METHODS } from '../common/types';
3
3
  import SDKConnector from '../SDKConnector';
4
4
  import log from '../Logger';
5
- import { CONTACTS_FILE, CONTACTS_SCHEMA, CONTACT_FILTER, DEFAULT_GROUP_NAME, ENCRYPT_FILTER, GROUP_FILTER, OR, SCIM_ID_FILTER, USERS, encryptedFields, } from './constants';
5
+ import { CONTACTS_FILE, CONTACTS_SCHEMA, CONTACT_FILTER, DEFAULT_GROUP_NAME, ENCRYPT_FILTER, GROUP_FILTER, METHODS, OR, SCIM_ID_FILTER, USERS, encryptedFields, } from './constants';
6
6
  import { ContactType, GroupType, } from './types';
7
- import { scimQuery, serviceErrorCodeHandler } from '../common/Utils';
7
+ import { scimQuery, serviceErrorCodeHandler, uploadLogs } from '../common/Utils';
8
8
  export class ContactsClient {
9
9
  sdkConnector;
10
10
  encryptionKeyUrl;
@@ -188,8 +188,9 @@ export class ContactsClient {
188
188
  async getContacts() {
189
189
  const loggerContext = {
190
190
  file: CONTACTS_FILE,
191
- method: 'getContacts',
191
+ method: METHODS.GET_CONTACTS,
192
192
  };
193
+ log.info(METHOD_START_MESSAGE, loggerContext);
193
194
  const contactList = [];
194
195
  const cloudContactsMap = {};
195
196
  try {
@@ -244,19 +245,24 @@ export class ContactsClient {
244
245
  },
245
246
  message: SUCCESS_MESSAGE,
246
247
  };
248
+ log.log('Successfully fetched contacts and groups', loggerContext);
247
249
  return contactResponse;
248
250
  }
249
251
  catch (err) {
250
252
  const errorInfo = err;
253
+ const extendedError = new Error(`Error fetching contacts: ${err}`);
254
+ log.error(extendedError, loggerContext);
251
255
  const errorStatus = serviceErrorCodeHandler(errorInfo, loggerContext);
256
+ await uploadLogs();
252
257
  return errorStatus;
253
258
  }
254
259
  }
255
260
  async createNewEncryptionKeyUrl() {
256
261
  const loggerContext = {
257
262
  file: CONTACTS_FILE,
258
- method: this.createNewEncryptionKeyUrl.name,
263
+ method: METHODS.CREATE_NEW_ENCRYPTION_KEY_URL,
259
264
  };
265
+ log.info(METHOD_START_MESSAGE, loggerContext);
260
266
  let unboundedKeyUri = '';
261
267
  log.info('Requesting kms for a new KRO and key', loggerContext);
262
268
  const unboundedKeys = await this.webex.internal.encryption.kms.createUnboundKeys({ count: 1 });
@@ -265,6 +271,11 @@ export class ContactsClient {
265
271
  return unboundedKeyUri;
266
272
  }
267
273
  async fetchEncryptionKeyUrl() {
274
+ const loggerContext = {
275
+ file: CONTACTS_FILE,
276
+ method: METHODS.FETCH_ENCRYPTION_KEY_URL,
277
+ };
278
+ log.info(METHOD_START_MESSAGE, loggerContext);
268
279
  if (this.encryptionKeyUrl) {
269
280
  return this.encryptionKeyUrl;
270
281
  }
@@ -275,45 +286,67 @@ export class ContactsClient {
275
286
  return this.groups[0].encryptionKeyUrl;
276
287
  }
277
288
  this.encryptionKeyUrl = await this.createNewEncryptionKeyUrl();
278
- log.info(`Creating a default group: ${DEFAULT_GROUP_NAME}`, {
289
+ log.log(`Creating a default group: ${DEFAULT_GROUP_NAME}`, {
279
290
  file: CONTACTS_FILE,
280
291
  method: this.fetchEncryptionKeyUrl.name,
281
292
  });
282
293
  const response = await this.createContactGroup(DEFAULT_GROUP_NAME, this.encryptionKeyUrl);
283
294
  if (response.data.group?.groupId) {
284
295
  this.defaultGroupId = response.data.group?.groupId;
296
+ log.log(`Successfully created default group with ID: ${this.defaultGroupId}`, {
297
+ file: CONTACTS_FILE,
298
+ method: this.fetchEncryptionKeyUrl.name,
299
+ });
285
300
  }
286
301
  return this.encryptionKeyUrl;
287
302
  }
288
303
  async fetchDefaultGroup() {
304
+ const loggerContext = {
305
+ file: CONTACTS_FILE,
306
+ method: METHODS.FETCH_DEFAULT_GROUP,
307
+ };
308
+ log.info(METHOD_START_MESSAGE, loggerContext);
289
309
  if (this.defaultGroupId) {
310
+ log.log(`Using existing default group with ID: ${this.defaultGroupId}`, {
311
+ file: CONTACTS_FILE,
312
+ method: this.fetchDefaultGroup.name,
313
+ });
290
314
  return this.defaultGroupId;
291
315
  }
292
316
  if (this.groups && this.groups.length) {
293
317
  for (let i = 0; i < this.groups.length; i += 1) {
294
318
  if (this.groups[i].displayName === DEFAULT_GROUP_NAME) {
295
319
  this.defaultGroupId = this.groups[i].groupId;
320
+ log.log(`Found default group with ID: ${this.defaultGroupId}`, {
321
+ file: CONTACTS_FILE,
322
+ method: this.fetchDefaultGroup.name,
323
+ });
296
324
  return this.defaultGroupId;
297
325
  }
298
326
  }
299
327
  }
300
- log.info('No default group found.', {
328
+ log.log('No default group found.', {
301
329
  file: CONTACTS_FILE,
302
330
  method: this.fetchDefaultGroup.name,
303
331
  });
304
332
  const response = await this.createContactGroup(DEFAULT_GROUP_NAME);
305
333
  const { group } = response.data;
306
334
  if (group) {
307
- return group.groupId;
335
+ const groupId = group.groupId;
336
+ log.log(`Successfully created new default group with ID: ${groupId}`, {
337
+ file: CONTACTS_FILE,
338
+ method: this.fetchDefaultGroup.name,
339
+ });
340
+ return groupId;
308
341
  }
309
342
  return '';
310
343
  }
311
344
  async createContactGroup(displayName, encryptionKeyUrl, groupType) {
312
345
  const loggerContext = {
313
346
  file: CONTACTS_FILE,
314
- method: this.createContactGroup.name,
347
+ method: METHODS.CREATE_CONTACT_GROUP,
315
348
  };
316
- log.info(`Creating contact group ${displayName}`, loggerContext);
349
+ log.info(`${METHOD_START_MESSAGE} with displayName: ${displayName}`, loggerContext);
317
350
  const encryptionKeyUrlFinal = encryptionKeyUrl || (await this.fetchEncryptionKeyUrl());
318
351
  if (this.groups === undefined) {
319
352
  await this.getContacts();
@@ -354,20 +387,24 @@ export class ContactsClient {
354
387
  message: SUCCESS_MESSAGE,
355
388
  };
356
389
  this.groups?.push(group);
390
+ log.log(`Contact group ${displayName} successfully created`, loggerContext);
357
391
  return contactResponse;
358
392
  }
359
393
  catch (err) {
360
- log.warn('Unable to create contact group.', loggerContext);
361
394
  const errorInfo = err;
395
+ const extendedError = new Error(`Unable to create contact group: ${err}`);
396
+ log.error(extendedError, loggerContext);
362
397
  const errorStatus = serviceErrorCodeHandler(errorInfo, loggerContext);
398
+ await uploadLogs();
363
399
  return errorStatus;
364
400
  }
365
401
  }
366
402
  async deleteContactGroup(groupId) {
367
403
  const loggerContext = {
368
404
  file: CONTACTS_FILE,
369
- method: this.deleteContactGroup.name,
405
+ method: METHODS.DELETE_CONTACT_GROUP,
370
406
  };
407
+ log.info(`${METHOD_START_MESSAGE} with groupId: ${groupId}`, loggerContext);
371
408
  try {
372
409
  log.info(`Deleting contact group: ${groupId}`, loggerContext);
373
410
  const response = await this.webex.request({
@@ -386,21 +423,24 @@ export class ContactsClient {
386
423
  if (!this.groups?.length) {
387
424
  this.defaultGroupId = '';
388
425
  }
426
+ log.log(`Contact group ${groupId} successfully deleted`, loggerContext);
389
427
  return contactResponse;
390
428
  }
391
429
  catch (err) {
392
- log.warn(`Unable to delete contact group ${groupId}`, loggerContext);
393
430
  const errorInfo = err;
431
+ const extendedError = new Error(`Unable to delete contact group ${groupId}: ${err}`);
432
+ log.error(extendedError, loggerContext);
394
433
  const errorStatus = serviceErrorCodeHandler(errorInfo, loggerContext);
434
+ await uploadLogs();
395
435
  return errorStatus;
396
436
  }
397
437
  }
398
438
  async createContact(contactInfo) {
399
439
  const loggerContext = {
400
440
  file: CONTACTS_FILE,
401
- method: this.createContact.name,
441
+ method: METHODS.CREATE_CONTACT,
402
442
  };
403
- log.info(`Request to create contact: contactType: ${contactInfo.contactType}`, loggerContext);
443
+ log.info(`${METHOD_START_MESSAGE} with contactType: ${contactInfo.contactType}`, loggerContext);
404
444
  try {
405
445
  const contact = { ...contactInfo };
406
446
  if (!contact.encryptionKeyUrl) {
@@ -467,23 +507,24 @@ export class ContactsClient {
467
507
  else {
468
508
  this.contacts?.push(contact);
469
509
  }
510
+ log.log(`Contact successfully created`, loggerContext);
470
511
  return contactResponse;
471
512
  }
472
513
  catch (err) {
473
- log.warn('Failed to create contact.', {
474
- file: CONTACTS_FILE,
475
- method: this.createContact.name,
476
- });
477
514
  const errorInfo = err;
515
+ const extendedError = new Error(`Failed to create contact: ${err}`);
516
+ log.error(extendedError, loggerContext);
478
517
  const errorStatus = serviceErrorCodeHandler(errorInfo, loggerContext);
518
+ await uploadLogs();
479
519
  return errorStatus;
480
520
  }
481
521
  }
482
522
  async deleteContact(contactId) {
483
523
  const loggerContext = {
484
524
  file: CONTACTS_FILE,
485
- method: this.deleteContact.name,
525
+ method: METHODS.DELETE_CONTACT,
486
526
  };
527
+ log.info(`${METHOD_START_MESSAGE} with contactId: ${contactId}`, loggerContext);
487
528
  try {
488
529
  log.info(`Deleting contact : ${contactId}`, loggerContext);
489
530
  const response = await this.webex.request({
@@ -499,12 +540,15 @@ export class ContactsClient {
499
540
  if (contactToDelete !== undefined && contactToDelete !== -1) {
500
541
  this.contacts?.splice(contactToDelete, 1);
501
542
  }
543
+ log.log(`Contact ${contactId} successfully deleted`, loggerContext);
502
544
  return contactResponse;
503
545
  }
504
546
  catch (err) {
505
- log.warn(`Unable to delete contact ${contactId}`, loggerContext);
506
547
  const errorInfo = err;
548
+ const extendedError = new Error(`Unable to delete contact ${contactId}: ${err}`);
549
+ log.error(extendedError, loggerContext);
507
550
  const errorStatus = serviceErrorCodeHandler(errorInfo, loggerContext);
551
+ await uploadLogs();
508
552
  return errorStatus;
509
553
  }
510
554
  }
@@ -20,3 +20,13 @@ export var encryptedFields;
20
20
  encryptedFields["SIP_ADDRESSES"] = "sipAddresses";
21
21
  encryptedFields["TITLE"] = "title";
22
22
  })(encryptedFields || (encryptedFields = {}));
23
+ export const METHODS = {
24
+ GET_CONTACTS: 'getContacts',
25
+ CREATE_NEW_ENCRYPTION_KEY_URL: 'createNewEncryptionKeyUrl',
26
+ FETCH_ENCRYPTION_KEY_URL: 'fetchEncryptionKeyUrl',
27
+ FETCH_DEFAULT_GROUP: 'fetchDefaultGroup',
28
+ CREATE_CONTACT_GROUP: 'createContactGroup',
29
+ DELETE_CONTACT_GROUP: 'deleteContactGroup',
30
+ CREATE_CONTACT: 'createContact',
31
+ DELETE_CONTACT: 'deleteContact',
32
+ };
@@ -7,12 +7,14 @@ export var ERROR_TYPE;
7
7
  (function (ERROR_TYPE) {
8
8
  ERROR_TYPE["CALL_ERROR"] = "call_error";
9
9
  ERROR_TYPE["DEFAULT"] = "default_error";
10
+ ERROR_TYPE["BAD_REQUEST"] = "bad_request";
10
11
  ERROR_TYPE["FORBIDDEN_ERROR"] = "forbidden";
11
12
  ERROR_TYPE["NOT_FOUND"] = "not_found";
12
13
  ERROR_TYPE["REGISTRATION_ERROR"] = "registration_error";
13
14
  ERROR_TYPE["SERVICE_UNAVAILABLE"] = "service_unavailable";
14
15
  ERROR_TYPE["TIMEOUT"] = "timeout";
15
16
  ERROR_TYPE["TOKEN_ERROR"] = "token_error";
17
+ ERROR_TYPE["TOO_MANY_REQUESTS"] = "too_many_requests";
16
18
  ERROR_TYPE["SERVER_ERROR"] = "server_error";
17
19
  })(ERROR_TYPE || (ERROR_TYPE = {}));
18
20
  export var ERROR_CODE;
@@ -4,7 +4,7 @@ import { LOG_PREFIX } from '../../Logger/types';
4
4
  export class Eventing extends EventEmitter {
5
5
  emit(event, ...args) {
6
6
  const timestamp = new Date().toUTCString();
7
- Logger.log(`${timestamp} ${LOG_PREFIX.EVENT}: ${event.toString()} - event emitted with parameters -> ${args} = `, {
7
+ Logger.info(`${timestamp} ${LOG_PREFIX.EVENT}: ${event.toString()} - event emitted with parameters -> ${args} = `, {
8
8
  file: 'Events/impl/index.ts',
9
9
  method: 'emit',
10
10
  });