Skip to content

Commit 6088b1b

Browse files
committed
chore: temporary stack-trace diagnostic for base DATE._stringify
Adds a gated (CADT_DATE_STRINGIFY_DIAG=1) stack-trace logger on the patched base _stringify, capped at 8 invocations per process so it can't spam logs or disk. Enabled in the V1 and V2 live-api Start-CADT steps so one CI run captures the full call stack for whatever Sequelize internal path is reaching the base serialiser on a mysql attribute type despite the mysql.DATE subclass being wired up. Remove this commit after the root cause is understood and the explanatory comment in src/config/config.js is updated with the concrete Sequelize call site.
1 parent 9571d6e commit 6088b1b

2 files changed

Lines changed: 60 additions & 2 deletions

File tree

.github/workflows/tests.yaml

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -314,12 +314,20 @@ jobs:
314314
315315
- name: Start CADT
316316
shell: bash
317+
env:
318+
# TEMPORARY: capture stack traces for the first few base
319+
# DATE._stringify invocations. One CI run pinpoints the
320+
# Sequelize internal path that reaches the base serialiser
321+
# despite mysql.DATE being wired up. Remove this env var once
322+
# the stacks are captured and the comment in src/config/config.js
323+
# is updated with the concrete root cause.
324+
CADT_DATE_STRINGIFY_DIAG: "1"
317325
run: |
318326
# MariaDB is still stopped at this point (see "Configure MySQL").
319327
# CADT must start successfully, log the mirror setup failure as
320328
# non-fatal, and expose its health endpoint. This exercises the
321329
# mirror init race that broke production observers on k8s.
322-
pm2 start npm --no-autorestart --name "cadt" -- start
330+
pm2 start npm --no-autorestart --name "cadt" --update-env -- start
323331
echo "Waiting for CADT health endpoint..."
324332
MAX_CADT_HEALTH_ATTEMPTS=30
325333
for CADT_ATTEMPT in $(seq 1 "$MAX_CADT_HEALTH_ATTEMPTS"); do
@@ -842,14 +850,22 @@ jobs:
842850
843851
- name: Start CADT
844852
shell: bash
853+
env:
854+
# TEMPORARY: capture stack traces for the first few base
855+
# DATE._stringify invocations. One CI run pinpoints the
856+
# Sequelize internal path that reaches the base serialiser
857+
# despite mysql.DATE being wired up. Remove this env var once
858+
# the stacks are captured and the comment in src/config/config.js
859+
# is updated with the concrete root cause.
860+
CADT_DATE_STRINGIFY_DIAG: "1"
845861
run: |
846862
# MariaDB is still stopped at this point (see "Configure MySQL
847863
# for V1 mirror database testing"). CADT must start successfully,
848864
# log the mirror setup failure as non-fatal, and expose its API.
849865
# The subsequent "Delay-start MariaDB" step restarts MariaDB
850866
# shortly after so the V1 mirror reconnect path is exercised
851867
# while CADT is still booting.
852-
pm2 start npm --no-autorestart --name "cadt" -- start
868+
pm2 start npm --no-autorestart --name "cadt" --update-env -- start
853869
echo "Waiting for CADT API endpoint (V1 port ${CW_PORT:-31310})..."
854870
MAX_CADT_HEALTH_ATTEMPTS=30
855871
for CADT_ATTEMPT in $(seq 1 "$MAX_CADT_HEALTH_ATTEMPTS"); do

src/config/config.js

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,52 @@ import { createHash } from 'crypto';
3232
// DATETIME(0) columns). CADT's mirror verification helpers
3333
// (tests/v{1,2}/live-api/helpers/mysql-mirror-helpers.js) compare on
3434
// the YYYY-MM-DD prefix only, so the rounding is not observable.
35+
36+
// Diagnostic counters for the patched base _stringify below. Gated by
37+
// CADT_DATE_STRINGIFY_DIAG so tests and production runs don't pay the
38+
// stack-capture cost or spam the logger. This block is TEMPORARY - it
39+
// exists to identify the specific Sequelize entry point that reaches
40+
// the base _stringify despite the mysql.DATE subclass being wired up.
41+
// Remove once that path is understood and documented in the comment
42+
// above.
43+
const MAX_BASE_STRINGIFY_STACKS = 8;
44+
let baseStringifyDiagCount = 0;
45+
const baseStringifyDiagEnabled =
46+
process.env.CADT_DATE_STRINGIFY_DIAG !== undefined
47+
? process.env.CADT_DATE_STRINGIFY_DIAG !== '0' &&
48+
process.env.CADT_DATE_STRINGIFY_DIAG !== 'false'
49+
: false;
50+
3551
Sequelize.DataTypes.DATE.prototype._stringify = function _stringify(
3652
date,
3753
options,
3854
) {
55+
// TEMPORARY DIAGNOSTIC - see MAX_BASE_STRINGIFY_STACKS block above.
56+
if (
57+
baseStringifyDiagEnabled &&
58+
baseStringifyDiagCount < MAX_BASE_STRINGIFY_STACKS
59+
) {
60+
baseStringifyDiagCount += 1;
61+
const stack = new Error('[DATE-diag]').stack
62+
.split('\n')
63+
.slice(1, 12)
64+
.join('\n');
65+
const valueStr =
66+
date instanceof Date
67+
? date.toISOString()
68+
: moment.isMoment(date)
69+
? date.toISOString()
70+
: String(date);
71+
const dialectHint = this?.constructor?.name || 'unknown';
72+
logger.warn(
73+
`[DATE-diag] base _stringify called ` +
74+
`(${baseStringifyDiagCount}/${MAX_BASE_STRINGIFY_STACKS}) ` +
75+
`value=${valueStr} ` +
76+
`timezone=${options?.timezone ?? 'unset'} ` +
77+
`this.constructor.name=${dialectHint}\n` +
78+
stack,
79+
);
80+
}
3981
if (!moment.isMoment(date)) {
4082
date = this._applyTimezone(date, options);
4183
}

0 commit comments

Comments
 (0)