Skip to main content

Change Document: v2.4.0.0 — Job Queue Batch Cap, Field Widening, and SecretText Migration

FieldValue
Version2.4.0.0
Date2026-03-11
ExtensionBC Dialing Application (Cambay Solutions)
SeverityHigh — resolves email backlog throughput issue and eliminates deprecation warnings
StatusImplemented — pending deployment

Background

Three issues converged to motivate this version:

  1. ISSUE-15 — Email backlog. Production telemetry showed 630+ pending email log records accumulating in the CustomerEmailLog table. The Job Queue codeunit (CU-60003) processes all pending records in a single run with no batch size limit. With each email log requiring 2 Nextiva API calls + 2 Azure Blob uploads, a 630-record run takes 30+ minutes — long enough to outlast the Nextiva auth token, causing cascading failures across all remaining records. Records that hit 3 failed attempts are permanently abandoned.

  2. Text field constraints. A recurring "The length of the string is 21, but it must be less than or equal to 20 characters" error was blocking recording and transcript sync. Multiple tables had Text[20] fields that were too narrow for production data — AssetType on NextivaData, PhoneNumber on CustomerPhoneLog, EmailAddress on CustomerEmailLog, and error log fields on Nextiva Error Logs.

  3. UseReadySAS deprecation. Both CU-60003 and CU-60004 used the deprecated UseReadySAS(Text) overload, generating AL0432 compiler warnings. This was listed as a v2.4.0.0 follow-up in the v2.3.0.0 CHANGE document.


Summary of Changes

#SeverityCategoryDescription
1HighAddedConfigurable batch cap for Job Queue processing — limits phone and email log records processed per run
2HighAddedImmediate abandonment for permanent failures — "Customer Not found" errors skip retries
3HighFixedWidened Text fields across 4 tables to prevent string length constraint errors
4MediumFixedMigrated UseReadySAS from deprecated Text to SecretText parameter type (AL0432 warning)
5MediumFixedEliminated double Get() + Modify(true) on success path — attempt increment folded into flag update
6LowChangedJob Queue startup telemetry (BCDIALER-1000) now uses Dictionary overload with batch cap values
7LowAddedBatch cap fields exposed on NextivaConfigAPI page for monitoring visibility
8LowAddedUpgrade codeunit populates batch cap defaults for pre-2.4.0.0 installs

Detailed Changes

1. Job Queue Batch Cap (High)

Files: src/Table/Tab80003.NextivaConfig.al, src/Page/Pag-80007.NextivaSetupPage.al, src/Codeunit/CU60003.NextivaIntegration.al

Problem: CU-60003's OnRun trigger processes every pending phone and email log record in a single Job Queue run. With no upper bound, a backlog of 630 email logs means:

  • 2,520+ HTTP round-trips per run (4 per phone log, 2 per email log)
  • 30+ minute run duration
  • Nextiva auth token likely expires mid-run, causing cascading failures
  • All failed records increment their Attempts counter toward the 3-attempt abandonment threshold

Fix: Two new Integer fields on NextivaConfig:

  • "Max Phone Logs Per Run" (field 7, default 50, range 1–1000)
  • "Max Email Logs Per Run" (field 8, default 50, range 1–1000)

Both processing loops in OnRun now check a BatchCount counter against the configured maximum. When the cap is reached, the loop exits with a BCDIALER-1002 telemetry message recording how many records were processed vs. errored, and the remaining records are deferred to the next Job Queue run.

The cap counts only actual processing attempts — records with empty NextivaSessionID are skipped without incrementing the counter.

Impact: With a 50-record batch cap and a 30-second Job Queue interval, a 630-record backlog clears in ~13 runs (~6.5 minutes) with predictable, bounded run duration per cycle.

2. Immediate Abandonment for Permanent Failures (High)

Files: src/Codeunit/CU60003.NextivaIntegration.al

Problem: When TryProcessPhoneLog or TryProcessEmailLog fails because no Customer matches the phone number or email address, the error is transient from the code's perspective — it increments Attempts and retries on the next run. But "Customer Not found" is a permanent condition: the Customer record won't appear between runs. Each retry burns one of three attempts and wastes an HTTP round-trip for the Customer lookup, contributing to backlog growth.

Fix: New AbandonRecord procedure sets Attempts := 3 immediately on the log record, removing it from the processing queue. The main loop checks GetLastErrorText() against a CustomerNotFoundTok label constant — if the error matches, AbandonRecord is called instead of UpdateAttempt. Abandoned records are logged as BCDIALER-5002 (Warning severity) with the SourceNo and SessionID.

The error text matching uses two named constants declared at the codeunit level:

  • CustomerNotFoundErr: Label 'Customer Not found with %1' — used in the Error() call
  • CustomerNotFoundTok: Label 'Customer Not found with' — used in the Contains() check

This eliminates the magic string duplication that would otherwise make the match fragile.

3. Text Field Widening (High)

Files: src/Table/Tab80001.NextivaData.al, src/Table/Tab80000.CustomerPhoneLog.al, src/Table/Tab80002.CustomerEmailLog.al, src/Table/Tab80004.NextivaErrorLogs.al

TableFieldBeforeAfterRationale
NextivaData (80001)AssetTypeText[20]Text[100]21-char value triggered runtime error; generous sizing for unknown Nextiva payload values
CustomerPhoneLog (80000)PhoneNumberText[20]Text[50]E.164 with extensions can exceed 20 chars
CustomerEmailLog (80002)EmailAddressText[20]Text[250]Email addresses routinely exceed 20 chars; aligns with the existing EmailAddress1 Text[255] workaround field
Nextiva Error Logs (80004)Source TypeText[20]Text[50]Room for longer source type identifiers
Nextiva Error Logs (80004)Error TitleText[20]Text[100]Error titles were being truncated

All changes are non-destructive column widenings — existing data is preserved, no reindex required.

4. SecretText Migration (Medium)

Files: src/Codeunit/CU60003.NextivaIntegration.al, src/Codeunit/CU-60004.NextivaIntegrationManual.al

Problem: Both codeunits used the deprecated UseReadySAS(Text) overload in TryInitializeAuth, generating AL0432 compiler warnings. The Text parameter type also meant the SAS token could appear in runtime logs.

Fix: Changed the CachedSASToken codeunit-level variable from Text to SecretText in both CU-60003 and CU-60004. The local SASToken variable in TryInitializeAuth is now SecretText. The hardcoded fallback token is assigned through an intermediate Text variable (FallbackToken) because AL does not allow implicit string literal → SecretText conversion. The UseReadySAS(SecretText) overload is now used, eliminating the deprecation warning.

Impact: Zero functional change. The SAS token is now protected from accidental exposure in runtime logs and telemetry.

5. Double Modify Elimination (Medium)

Files: src/Codeunit/CU60003.NextivaIntegration.al

Problem: On the success path, both UpdateAllPhoneLogFlags and UpdateAttempt performed separate Get() + Modify(true) calls on the same phone/email log record. Two database round-trips per successful record — 100 unnecessary DB operations per 50-record batch.

Fix: Folded the Attempts += 1 increment into UpdateAllPhoneLogFlags and UpdateAllEmailLogFlags. Removed the separate UpdateAttempt call from the success path in both processing loops. The failure path still calls UpdateAttempt or AbandonRecord separately (both do their own Get() + Modify(true)), which is acceptable since failures are infrequent.

6. Startup Telemetry Enhancement (Low)

Files: src/Codeunit/CU60003.NextivaIntegration.al

The BCDIALER-1000 startup telemetry message now includes MaxPhoneLogs and MaxEmailLogs dimensions alongside the existing PendingPhoneLogs and PendingEmailLogs counts. Uses the Dictionary of [Text, Text] overload instead of individual key-value pairs (which only supports 2 pairs).

7. Config API Page Update (Low)

Files: src/Page/Pag-80010.NextivaConfigAPI.al

Added maxPhoneLogsPerRun and maxEmailLogsPerRun fields to the read-only API page. Enables monitoring tools and integration tests to verify batch cap configuration without accessing the BC UI.

8. Upgrade Codeunit — Batch Cap Defaults (Low)

Files: src/Codeunit/CU-60005.DialerUpgrade.al

New PopulateBatchCapDefaults procedure runs for upgrades from versions below 2.4.0.0. Sets "Max Phone Logs Per Run" and "Max Email Logs Per Run" to 50 on the existing config record if the field value is 0 (pre-upgrade state). A Changed boolean guard prevents unnecessary Modify() calls when both fields are already populated.


Object Inventory

Object IDObject TypeNameStatus
60003CodeunitNextiva IntegrationModified — batch cap, abandonment, SecretText, double Modify fix, telemetry
60004CodeunitNextiva Integration ManualModified — SecretText migration
60005CodeunitDialer UpgradeModified — batch cap defaults procedure
80000TableCustomerPhoneLogModified — PhoneNumber widened to Text[50]
80001TableNextivaDataModified — AssetType widened to Text[100]
80002TableCustomerEmailLogModified — EmailAddress widened to Text[250]
80003TableNextivaConfigModified — two new Integer fields (Max Phone/Email Logs Per Run)
80004TableNextiva Error LogsModified — Source Type widened to Text[50], Error Title widened to Text[100]
80007PageNextivaSetupModified — Job Queue Settings group with batch cap fields
80010PageNextivaConfigAPIModified — batch cap fields exposed
app.jsonExtension manifestModified — version bump to 2.4.0.0

Known Limitations

Hardcoded Credential Fallbacks Still Present (Transitional)

The v2.3.0.0 CHANGE document recommended removing hardcoded fallbacks in v2.4.0.0. This was deferred to keep v2.4.0.0 focused on the batch cap and field widening fixes. The fallbacks continue to emit telemetry warnings (BCDIALER-0001 through BCDIALER-0003) when activated. Removal is planned for v2.5.0.0.

Azure Storage Account and Container Not Yet Externalized

Still hardcoded as p360data and nextiva-bc in CU-60003 and CU-60004. Deferred from v2.3.0.0, still deferred.

No Automated Tests

The extension has no AL test codeunits. The batch cap and abandonment logic would benefit from unit tests but are deferred pending extraction of business logic into testable helper codeunits.

Batch Cap Does Not Account for Empty-Session Records

The batch counter only increments for records with a non-empty NextivaSessionID. In a pathological case with many empty-session records interspersed among valid ones, the loop could scan more records than the configured maximum. Empty-session records should not exist in practice (API pages require a session ID), and the cap still enforces a hard limit on actual processing work.


Deployment Notes

Pre-Deployment

  • No manual configuration required. The upgrade codeunit sets batch cap defaults automatically.
  • No new dependencies.
  • Schema changes (Text field widening, new Integer fields) are non-destructive and handled automatically by BC during upgrade.

Deployment

  1. Build the .app package via AL: Package in VS Code
  2. Deploy to the target environment via Extension Management or the admin center
  3. The upgrade codeunit runs automatically during installation

Post-Deployment Verification

  1. Verify batch cap configuration via OData:

    GET /api/CambaySolutions/PhoneIntegration/v1.0/nextivaConfigs

    Confirm maxPhoneLogsPerRun = 50 and maxEmailLogsPerRun = 50.

  2. Verify via Nextiva Config Setup page (80007): New "Job Queue Settings" group should show both batch cap fields with value 50.

  3. Monitor Application Insights for the first hour:

    • BCDIALER-1000 events should show MaxPhoneLogs=50 and MaxEmailLogs=50 in custom dimensions
    • BCDIALER-1002 events indicate the batch cap was reached — expected during backlog drain
    • BCDIALER-5002 events indicate permanent failure abandonment — review these to identify missing Customer records
    • No AL0432 compiler warnings in the build output
  4. Monitor backlog drain: With a 50-record cap and 30-second Job Queue interval, the 630-record email backlog should clear within ~15 minutes. Track via BCDIALER-1000 pending counts decreasing over successive runs.


Testing

Key scenarios for this version:

#ScenarioExpected Result
1Job Queue with > 50 pending phone logsProcesses exactly 50, logs BCDIALER-1002, remaining deferred to next run
2Job Queue with > 50 pending email logsSame as above for emails
3Job Queue with < 50 pending recordsProcesses all, no BCDIALER-1002 event
4Phone log with no matching CustomerRecord immediately abandoned (Attempts set to 3), BCDIALER-5002 logged, no retry on next run
5Email log with no matching CustomerSame as above for emails
6Transient failure (Nextiva API timeout)Attempts incremented by 1, record retried on next run (up to 3 attempts)
7AssetType value > 20 charactersNo error — field now Text[100]
8Phone number > 20 charactersNo error — field now Text[50]
9Email address > 20 charactersNo error — field now Text[250]
10Batch cap fields visible on Config Setup page"Job Queue Settings" group shows both fields with default 50
11Batch cap fields visible on Config APIOData response includes maxPhoneLogsPerRun and maxEmailLogsPerRun
12Azure Blob upload uses SecretText SAS tokenNo AL0432 deprecation warnings; blob uploads succeed as before
13Upgrade from 2.3.6.0Batch cap fields auto-populated to 50; existing config values preserved