Skip to content

feat: initial support for scheduled measurements#797

Merged
MartinKolarik merged 64 commits into
masterfrom
gh-291
May 6, 2026
Merged

feat: initial support for scheduled measurements#797
MartinKolarik merged 64 commits into
masterfrom
gh-291

Conversation

@MartinKolarik
Copy link
Copy Markdown
Member

@MartinKolarik MartinKolarik commented Feb 13, 2026

Part of #291, but the system is intentionally generic to support custom user-scheduled measurements as well in the future.

Key concepts

Schedule defines a single logical target, how often it's tested, and which probes it runs on.
Configuration defines a measurement template. E.g., if we wanted to test CDN providers with three different file sizes, that would be three configurations within a single schedule.

Scheduling is handled by the API in the end, as it is much more efficient (in terms of storage, API requests for multiple results, etc.) to group multiple probe results into a single measurement. With probe-level scheduling, that would be rather difficult. Two scheduling modes:

  • stream - distributes the load on the target over time (each instance schedules its own probes at a different time)
  • batch - all probes run at once, same as if manually creating measurements with a cron job (not implemented yet)

@MartinKolarik
Copy link
Copy Markdown
Member Author

Yes, I was using the migrations here during dev, but will add them now.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/lib/server.ts (1)

101-106: ⚠️ Potential issue | 🟡 Minor

Missing graceful shutdown for scheduleExecutor.

The StreamScheduleExecutor has a stop() method that clears active timers and removes listeners, but it's never called during server termination. This could result in timer callbacks firing after other components (Redis clients, WS server) have been torn down.

Proposed fix
 	reconnectProbes(fetchRawSockets);
 	// Disconnect probes shortly before shutdown to prevent data loss.
 	termListener.on('terminating', ({ delay }) => setTimeout(() => void disconnectProbes(fetchRawSockets, 0), delay - 10000));
+	termListener.on('terminating', () => scheduleExecutor.stop());
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/lib/server.ts` around lines 101 - 106, The StreamScheduleExecutor
instance (scheduleExecutor) isn't stopped on shutdown, so its timers/listeners
can fire after other components are torn down; update the termination handling
to call scheduleExecutor.stop() inside the termListener 'terminating' handler
(before calling disconnectProbes(fetchRawSockets, 0)) so timers are cleared and
listeners removed during shutdown, e.g., invoke scheduleExecutor.stop() in the
same setTimeout callback (or immediately in the handler) to ensure the executor
is cleanly stopped prior to Redis/WS teardown.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docker-compose.dev.yml`:
- Around line 133-144: The new time-series-1-migrator service is not
self-contained because it mounts only ./:/app and assumes local node_modules;
update the time-series-1-migrator service (image node:22-alpine, working_dir
/app, volumes ./:/app, command npm run knex:time-series-1 migrate:latest) so it
installs dependencies inside the container before running the migration (e.g.,
run npm ci or npm install in the container or add a dedicated bind for
node_modules) so the project CLI binary for knex is available when executing the
migration.

---

Outside diff comments:
In `@src/lib/server.ts`:
- Around line 101-106: The StreamScheduleExecutor instance (scheduleExecutor)
isn't stopped on shutdown, so its timers/listeners can fire after other
components are torn down; update the termination handling to call
scheduleExecutor.stop() inside the termListener 'terminating' handler (before
calling disconnectProbes(fetchRawSockets, 0)) so timers are cleared and
listeners removed during shutdown, e.g., invoke scheduleExecutor.stop() in the
same setTimeout callback (or immediately in the handler) to ensure the executor
is cleanly stopped prior to Redis/WS teardown.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 0000788f-06b3-4115-a9ed-e9a8a7a486ca

📥 Commits

Reviewing files that changed from the base of the PR and between ddc10c2 and 4f33e8f.

📒 Files selected for processing (5)
  • .github/workflows/ci.yml
  • .github/workflows/e2e.yml
  • docker-compose.dev.yml
  • migrations/dashboard/create-tables.js.sql
  • src/lib/server.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • migrations/dashboard/create-tables.js.sql
  • .github/workflows/e2e.yml

Comment thread docker-compose.dev.yml
@MartinKolarik MartinKolarik force-pushed the master branch 3 times, most recently from a03a68e to 0460718 Compare April 4, 2026 11:42
@MartinKolarik MartinKolarik force-pushed the master branch 3 times, most recently from 6ce3160 to d51251d Compare April 20, 2026 22:17
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@test/e2e/cases/probe-logs.test.ts`:
- Line 146: The call to waitProbeToConnect() can hang because it has no internal
timeout; wrap this call at the test site with an explicit bounded wait (e.g.,
Promise.race or a helper like withTimeout) so the test fails deterministically
after a chosen timeout (e.g., 5–10s) and throws a clear error on timeout; update
the invocation replacing await waitProbeToConnect() with the bounded-wait
variant and assert/throw when the timeout wins to avoid silent hanging.

In `@test/tests/unit/measurement/store.test.ts`:
- Line 860: Tests are passing objects or malformed strings into Buffer.from when
stubbing compressed Redis payloads; update the three occurrences that set
redisMock.compressedJsonGetBufferCompressed (including the one shown) to call
buildMinimalMeasurementString('SOME_ID', { from: 'redis' }) and then pass its
result into Buffer.from(...) before brotliCompress, and fix the malformed-quote
instance (line ~878) to use the same buildMinimalMeasurementString call so all
compressed fixtures use a proper string payload; locate usages via
redisMock.compressedJsonGetBufferCompressed, brotliCompress,
buildMinimalMeasurementString and buildMinimalMeasurement to make the changes.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 8fb51126-a608-487d-a3b5-70bbcda870d7

📥 Commits

Reviewing files that changed from the base of the PR and between 4f33e8f and cd8e36f.

📒 Files selected for processing (10)
  • .github/workflows/ci.yml
  • .github/workflows/e2e.yml
  • config/default.cjs
  • docker-compose.dev.yml
  • package.json
  • src/measurement/store-offloader.ts
  • src/measurement/store.ts
  • test/e2e/cases/probe-logs.test.ts
  • test/tests/unit/measurement/store.test.ts
  • test/tests/unit/ws/synced-probe-list.test.ts
✅ Files skipped from review due to trivial changes (3)
  • config/default.cjs
  • src/measurement/store.ts
  • package.json
🚧 Files skipped from review as they are similar to previous changes (5)
  • .github/workflows/ci.yml
  • src/measurement/store-offloader.ts
  • .github/workflows/e2e.yml
  • test/tests/unit/ws/synced-probe-list.test.ts
  • docker-compose.dev.yml

Comment thread test/e2e/cases/probe-logs.test.ts
Comment thread test/tests/unit/measurement/store.test.ts Outdated
@MartinKolarik
Copy link
Copy Markdown
Member Author

@coderabbitai full review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 3, 2026

✅ Actions performed

Full review triggered.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/measurement/types.ts (1)

207-220: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Keep schedule metadata out of UserRequest.

Because UserRequest now omits only locations and limit, public callers can also pass scheduleId and configurationId. Unless that is intentional, this exposes internal scheduling fields on the user-facing request contract and lets user input be persisted as schedule metadata. Exclude those fields from UserRequest explicitly.

Suggested fix
-export type UserRequest = Omit<MeasurementRequest, 'locations' | 'limit'> & {
+export type UserRequest = Omit<MeasurementRequest, 'locations' | 'limit' | 'scheduleId' | 'configurationId'> & {
 	locations: LocationWithLimit[] | string;
 	limit: number;
 };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/measurement/types.ts` around lines 207 - 220, UserRequest currently uses
Omit<MeasurementRequest, 'locations' | 'limit'> which still allows scheduleId
and configurationId to be supplied by callers; update the UserRequest definition
to explicitly exclude scheduling fields by omitting 'scheduleId' and
'configurationId' as well (e.g., use Omit<MeasurementRequest, 'locations' |
'limit' | 'scheduleId' | 'configurationId'> or build a new type that does not
include scheduleId/configurationId) so public callers cannot pass schedule
metadata; refer to the UserRequest and MeasurementRequest type names and the
scheduleId/configurationId symbols when making the change.
♻️ Duplicate comments (4)
migrations/time-series-1/20251204163412_create-tables.js (1)

81-81: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Implement a real rollback in down().

A no-op down() makes migration rollback ineffective and leaves time-series tables behind.

Suggested patch
-export const down = () => {};
+export const down = async (db) => {
+	await db.schema.dropTableIfExists('test_http_failed');
+	await db.schema.dropTableIfExists('test_http');
+	await db.schema.dropTableIfExists('test_dns_failed');
+	await db.schema.dropTableIfExists('test_dns');
+};
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@migrations/time-series-1/20251204163412_create-tables.js` at line 81, The
down() migration is currently a no-op so rolling back leaves the created
time-series tables in place; implement down() to drop all tables and related
objects created in up(), e.g. drop the time-series tables, any hypertables,
indexes, and sequences created by the migration (match the same names used in
up()), and ensure the SQL uses IF EXISTS to avoid errors during rollback; locate
the export const down = () => {} and replace it with a function that executes
the appropriate DROP TABLE / DROP INDEX / DROP SEQUENCE (or drop_hypertable)
statements for each object created in up().
migrations/dashboard/create-tables.js.sql (2)

114-115: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Enforce JSON shape, not only JSON validity.

json_valid(...) allows scalar/incorrect JSON shapes. locations should be an array and measurement_options should be an object.

Suggested schema patch
 	locations LONGTEXT CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL DEFAULT '[]'
-		CHECK (json_valid(locations)),
+		CHECK (json_valid(locations) AND JSON_TYPE(locations) = 'ARRAY'),
 	measurement_options LONGTEXT CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL DEFAULT '{}'
-		CHECK (json_valid(`measurement_options`)),
+		CHECK (json_valid(`measurement_options`) AND JSON_TYPE(`measurement_options`) = 'OBJECT'),

Also applies to: 132-133

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@migrations/dashboard/create-tables.js.sql` around lines 114 - 115, The
current CHECK constraints only use json_valid(...) which allows scalars; update
the constraints for the columns locations and measurement_options to assert both
validity and shape: keep json_valid(locations) AND require JSON_TYPE(locations)
= 'ARRAY' (or JSON_EXTRACT(locations, '$') IS JSON_ARRAY) and keep
json_valid(measurement_options) AND require JSON_TYPE(measurement_options) =
'OBJECT' (or JSON_EXTRACT(measurement_options, '$') IS JSON_OBJECT); apply these
combined checks where the CREATE TABLE defines columns locations and
measurement_options so the DB enforces array vs object shapes, not just JSON
validity.

112-113: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Disallow zero schedule intervals at the DB layer.

INT UNSIGNED still allows 0. Add a CHECK constraint so invalid intervals can’t be stored.

Suggested schema patch
 	`interval` INT UNSIGNED NOT NULL,
+	CONSTRAINT gp_schedule_interval_positive CHECK (`interval` > 0),
 	probe_limit INT UNSIGNED NULL,
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@migrations/dashboard/create-tables.js.sql` around lines 112 - 113, Add a
DB-level CHECK to prevent storing zero for the `interval` column (which is
currently defined as `interval INT UNSIGNED NOT NULL`) so only positive
intervals are allowed; modify the table DDL (or ALTER TABLE for existing schema)
to include a constraint (e.g., a CHECK named like
`chk_<table>_interval_positive`) that enforces `interval > 0`, ensuring existing
`probe_limit` and other columns remain unchanged.
src/schedule/types.ts (1)

1-2: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Use type-only imports for MeasurementOptions and Location.

These imports are type-only in this file; keeping them as value imports can break at runtime under strict TS module settings.

Suggested patch
-import { MeasurementOptions } from '../measurement/types.js';
-import { Location } from '../lib/location/types.js';
+import type { MeasurementOptions } from '../measurement/types.js';
+import type { Location } from '../lib/location/types.js';
#!/bin/bash
# Verify whether strict module settings make value imports for type-only symbols unsafe.
fd -i 'tsconfig*.json' -x rg -n '"verbatimModuleSyntax"|"importsNotUsedAsValues"|"preserveValueImports"' {}
rg -n "export type\\s+MeasurementOptions|export\\s+type\\s+Location|export\\s+interface\\s+Location" src/measurement/types.ts src/lib/location/types.ts
rg -n "^import \\{ MeasurementOptions \\}|^import \\{ Location \\}" src/schedule/types.ts

Expected result: if strict module-preservation settings are enabled and exports are type-only, this import form should be converted to import type.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/schedule/types.ts` around lines 1 - 2, The imports of MeasurementOptions
and Location are used only as types and should be converted to type-only imports
to avoid runtime errors under strict module settings; replace the current value
imports with type-only imports (use "import type { MeasurementOptions } from
'../measurement/types.js'" and "import type { Location } from
'../lib/location/types.js' for the symbols MeasurementOptions and Location) so
the compiler strips them from emitted JS while preserving type information.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/ci.yml:
- Around line 47-59: CI starts the postgresTimeSeries service but does not run
the time-series migrations, causing missing-table errors; update the workflow to
run the migration command (knex:time-series-1 migrate:latest) after the
postgresTimeSeries service is up and healthy and before running the test
commands. Specifically, add a step that waits for postgresTimeSeries health and
then runs the migration (using the same environment variables or service
container name) so tests execute only after migration completes.

In @.github/workflows/e2e.yml:
- Around line 47-59: Add a pre-test step that runs the time-series DB migrations
against the new postgresTimeSeries service before executing npm run test:e2e;
modify the GitHub Actions job that currently runs npm run test:e2e to insert a
migration step (e.g., the repository's timeseries migration script or CLI
command) which targets the postgresTimeSeries instance so required tables are
created prior to the E2E tests.

In `@src/time-series/writer.ts`:
- Around line 8-22: The records are being stamped with the write/offload time
via timeSeriesClient.fn.now() instead of the original measurement timestamp,
which breaks time-series accuracy and the (measurementId, testId, createdAt)
uniqueness on retries; add a createdAt: string (or Date) field to
TimeSeriesDnsRecord and TimeSeriesHttpRecord, thread the measurement's original
createdAt through the code paths that build these records, and replace uses of
timeSeriesClient.fn.now() in the writer that set createdAt with the incoming
record.createdAt so the DB insert uses the measurement timestamp for both
storage and uniqueness checks.

---

Outside diff comments:
In `@src/measurement/types.ts`:
- Around line 207-220: UserRequest currently uses Omit<MeasurementRequest,
'locations' | 'limit'> which still allows scheduleId and configurationId to be
supplied by callers; update the UserRequest definition to explicitly exclude
scheduling fields by omitting 'scheduleId' and 'configurationId' as well (e.g.,
use Omit<MeasurementRequest, 'locations' | 'limit' | 'scheduleId' |
'configurationId'> or build a new type that does not include
scheduleId/configurationId) so public callers cannot pass schedule metadata;
refer to the UserRequest and MeasurementRequest type names and the
scheduleId/configurationId symbols when making the change.

---

Duplicate comments:
In `@migrations/dashboard/create-tables.js.sql`:
- Around line 114-115: The current CHECK constraints only use json_valid(...)
which allows scalars; update the constraints for the columns locations and
measurement_options to assert both validity and shape: keep
json_valid(locations) AND require JSON_TYPE(locations) = 'ARRAY' (or
JSON_EXTRACT(locations, '$') IS JSON_ARRAY) and keep
json_valid(measurement_options) AND require JSON_TYPE(measurement_options) =
'OBJECT' (or JSON_EXTRACT(measurement_options, '$') IS JSON_OBJECT); apply these
combined checks where the CREATE TABLE defines columns locations and
measurement_options so the DB enforces array vs object shapes, not just JSON
validity.
- Around line 112-113: Add a DB-level CHECK to prevent storing zero for the
`interval` column (which is currently defined as `interval INT UNSIGNED NOT
NULL`) so only positive intervals are allowed; modify the table DDL (or ALTER
TABLE for existing schema) to include a constraint (e.g., a CHECK named like
`chk_<table>_interval_positive`) that enforces `interval > 0`, ensuring existing
`probe_limit` and other columns remain unchanged.

In `@migrations/time-series-1/20251204163412_create-tables.js`:
- Line 81: The down() migration is currently a no-op so rolling back leaves the
created time-series tables in place; implement down() to drop all tables and
related objects created in up(), e.g. drop the time-series tables, any
hypertables, indexes, and sequences created by the migration (match the same
names used in up()), and ensure the SQL uses IF EXISTS to avoid errors during
rollback; locate the export const down = () => {} and replace it with a function
that executes the appropriate DROP TABLE / DROP INDEX / DROP SEQUENCE (or
drop_hypertable) statements for each object created in up().

In `@src/schedule/types.ts`:
- Around line 1-2: The imports of MeasurementOptions and Location are used only
as types and should be converted to type-only imports to avoid runtime errors
under strict module settings; replace the current value imports with type-only
imports (use "import type { MeasurementOptions } from '../measurement/types.js'"
and "import type { Location } from '../lib/location/types.js' for the symbols
MeasurementOptions and Location) so the compiler strips them from emitted JS
while preserving type information.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a4553f99-3bae-4957-89ee-c40ddd5379a1

📥 Commits

Reviewing files that changed from the base of the PR and between 2724852 and 068af6b.

📒 Files selected for processing (30)
  • .github/workflows/ci.yml
  • .github/workflows/e2e.yml
  • config/default.cjs
  • config/development.cjs
  • config/test.cjs
  • config/time-series-1/create-dbs.sql
  • docker-compose.dev.yml
  • knexfile.time-series-1.js
  • migrations/dashboard/create-tables.js.sql
  • migrations/measurement-store-1/20260130135153_add-schedules.js
  • migrations/time-series-1/20251204163412_create-tables.js
  • migrations/time-series-1/README.md
  • migrations/time-series-1/migration.stub
  • package.json
  • seeds/dashboard/development/index.js
  • seeds/time-series-1/test/index.js
  • src/lib/server.ts
  • src/lib/sql/client.ts
  • src/measurement/store-offloader.ts
  • src/measurement/store.ts
  • src/measurement/types.ts
  • src/schedule/executor.ts
  • src/schedule/loader.ts
  • src/schedule/types.ts
  • src/time-series/writer.ts
  • test/e2e/cases/probe-logs.test.ts
  • test/tests/integration/schedule/stream-schedule.test.ts
  • test/tests/unit/measurement/store.test.ts
  • test/tests/unit/ws/reconnect-probes.test.ts
  • test/tests/unit/ws/synced-probe-list.test.ts

Comment thread .github/workflows/ci.yml
Comment thread .github/workflows/e2e.yml
Comment thread src/time-series/writer.ts Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
package.json (1)

148-148: ⚡ Quick win

Reuse the new time-series Knex script here.

This inlines the same Knex command in two places, so any future change to the time-series invocation has to be updated manually in both spots.

♻️ Proposed fix
- "test:portman:setup": "NODE_ENV=test knex --knexfile knexfile.measurement-store-1.js migrate:latest && NODE_ENV=test knex --knexfile knexfile.measurement-store-1.js seed:run && NODE_ENV=test knex --knexfile knexfile.time-series-1.js migrate:latest && NODE_ENV=test knex --knexfile knexfile.time-series-1.js seed:run",
+ "test:portman:setup": "NODE_ENV=test knex --knexfile knexfile.measurement-store-1.js migrate:latest && NODE_ENV=test knex --knexfile knexfile.measurement-store-1.js seed:run && NODE_ENV=test npm run knex:time-series-1 -- migrate:latest && NODE_ENV=test npm run knex:time-series-1 -- seed:run",
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@package.json` at line 148, Replace the duplicated inline Knex invocation for
the time-series DB in the "test:portman:setup" npm script with a single reusable
npm script: extract the two commands that reference knexfile.time-series-1.js
(both migrate:latest and seed:run) into a new script (e.g.,
"test:time-series:setup") and then call that new script from
"test:portman:setup" using "npm run <new-script>" instead of repeating the full
Knex commands; update the "test:portman:setup" script to run the new script so
future changes to the time-series invocation are centralized.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@package.json`:
- Line 148: Replace the duplicated inline Knex invocation for the time-series DB
in the "test:portman:setup" npm script with a single reusable npm script:
extract the two commands that reference knexfile.time-series-1.js (both
migrate:latest and seed:run) into a new script (e.g., "test:time-series:setup")
and then call that new script from "test:portman:setup" using "npm run
<new-script>" instead of repeating the full Knex commands; update the
"test:portman:setup" script to run the new script so future changes to the
time-series invocation are centralized.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: fa579171-8925-42d7-8b3b-4b0e53fd5458

📥 Commits

Reviewing files that changed from the base of the PR and between ec5e609 and 689a86b.

📒 Files selected for processing (4)
  • package.json
  • test/e2e/docker.ts
  • test/e2e/setup.ts
  • test/setup.ts

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
.github/workflows/ci.yml (1)

61-79: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Run time-series migrations before the test stage.

postgresTimeSeries is provisioned, but the workflow still runs tests without an explicit knex:time-series-1 migrate:latest step. This can fail with missing relations when time-series paths are exercised.

Suggested patch
       - name: Build
         run: |
           npm ci
           npm run build
+      - name: Migrate time-series DB
+        run: |
+          NODE_ENV=test npm run knex:time-series-1 migrate:latest
       - name: Test Unit, Integration, Contract
         run: |
           npm run lint
           npm run coverage
           npm run test:portman
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/ci.yml around lines 61 - 79, Add a CI step that runs the
time-series migrations before the test step: after services (postgresTimeSeries)
and dependencies are up and before the "Test Unit, Integration, Contract" step,
invoke the migration command (e.g. run the npm script or CLI command that
executes "knex:time-series-1 migrate:latest") against the provisioned
postgresTimeSeries instance so time-series relations exist when tests run; place
this new step immediately prior to the test step in the workflow.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In @.github/workflows/ci.yml:
- Around line 61-79: Add a CI step that runs the time-series migrations before
the test step: after services (postgresTimeSeries) and dependencies are up and
before the "Test Unit, Integration, Contract" step, invoke the migration command
(e.g. run the npm script or CLI command that executes "knex:time-series-1
migrate:latest") against the provisioned postgresTimeSeries instance so
time-series relations exist when tests run; place this new step immediately
prior to the test step in the workflow.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 0d16c4d4-72fc-4ff7-9feb-842f43d0878b

📥 Commits

Reviewing files that changed from the base of the PR and between 689a86b and 753d87e.

📒 Files selected for processing (3)
  • .github/workflows/ci.yml
  • .github/workflows/e2e.yml
  • docker-compose.dev.yml
🚧 Files skipped from review as they are similar to previous changes (2)
  • .github/workflows/e2e.yml
  • docker-compose.dev.yml

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (2)
.github/workflows/ci.yml (1)

47-59: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Run time-series migrations before the test suite.

Line 47 adds the postgresTimeSeries service, but the workflow still does not run knex:time-series-1 migrate:latest before tests. That can cause missing-table/hypertable failures when time-series paths are exercised.

Suggested patch
       - name: Build
         run: |
           npm ci
           npm run build
+      - name: Migrate time-series DB
+        run: |
+          NODE_ENV=test npm run knex:time-series-1 migrate:latest
       - name: Test Unit, Integration, Contract
         run: |
           npm run lint
           npm run coverage
           npm run test:portman
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/ci.yml around lines 47 - 59, The workflow adds the
postgresTimeSeries service but never runs time-series DB migrations, causing
missing hypertable errors; update the CI job that runs tests to execute the
time-series migration command (run knex:time-series-1 migrate:latest or the
project's equivalent migration script) after the postgresTimeSeries service is
healthy and before running the test suite (reference the postgresTimeSeries
service name and the migration task knex:time-series-1 migrate:latest to locate
where to insert the step).
.github/workflows/e2e.yml (1)

47-59: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Migrate the time-series database before E2E execution.

Line 47 introduces postgresTimeSeries, but there is still no migration step before npm run test:e2e. This can break E2E flows that touch time-series persistence.

Suggested patch
       - name: Build
         run: |
           npm ci
           npm run build
+      - name: Migrate time-series DB
+        run: |
+          NODE_ENV=test npm run knex:time-series-1 migrate:latest
       - name: Test E2E
         run: |
           npm run test:e2e
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/e2e.yml around lines 47 - 59, Add a workflow step before
the test runner to migrate the time-series DB: after the postgresTimeSeries
service is healthy but before running npm run test:e2e, add a step that runs the
project's time-series migration command (e.g., npm run migrate:timeseries or the
equivalent CLI you use) and point it to the service connection (host localhost,
port 15442, POSTGRES_DB/POSTGRES_USER/POSTGRES_PASSWORD env vars used by
postgresTimeSeries); ensure the step waits for service health, exports those env
vars for the migration command, and fails the job if the migration returns a
non-zero exit code so tests never run against an unmigrated DB.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In @.github/workflows/ci.yml:
- Around line 47-59: The workflow adds the postgresTimeSeries service but never
runs time-series DB migrations, causing missing hypertable errors; update the CI
job that runs tests to execute the time-series migration command (run
knex:time-series-1 migrate:latest or the project's equivalent migration script)
after the postgresTimeSeries service is healthy and before running the test
suite (reference the postgresTimeSeries service name and the migration task
knex:time-series-1 migrate:latest to locate where to insert the step).

In @.github/workflows/e2e.yml:
- Around line 47-59: Add a workflow step before the test runner to migrate the
time-series DB: after the postgresTimeSeries service is healthy but before
running npm run test:e2e, add a step that runs the project's time-series
migration command (e.g., npm run migrate:timeseries or the equivalent CLI you
use) and point it to the service connection (host localhost, port 15442,
POSTGRES_DB/POSTGRES_USER/POSTGRES_PASSWORD env vars used by
postgresTimeSeries); ensure the step waits for service health, exports those env
vars for the migration command, and fails the job if the migration returns a
non-zero exit code so tests never run against an unmigrated DB.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 6f9d86ec-fbf1-4a93-9539-23bdf6cebcea

📥 Commits

Reviewing files that changed from the base of the PR and between 753d87e and e43d6a5.

📒 Files selected for processing (3)
  • .github/workflows/ci.yml
  • .github/workflows/e2e.yml
  • docker-compose.dev.yml
✅ Files skipped from review due to trivial changes (1)
  • docker-compose.dev.yml

@MartinKolarik MartinKolarik merged commit 08d9911 into master May 6, 2026
6 checks passed
@MartinKolarik MartinKolarik deleted the gh-291 branch May 6, 2026 20:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants