Skip to content

feat: add tenant_schedule database table for manifest-driven scheduling#2148

Merged
bjcoombs merged 4 commits intodevelopfrom
per-tenant-scheduling--8--tenant-schedule-table
Apr 7, 2026
Merged

feat: add tenant_schedule database table for manifest-driven scheduling#2148
bjcoombs merged 4 commits intodevelopfrom
per-tenant-scheduling--8--tenant-schedule-table

Conversation

@bjcoombs
Copy link
Copy Markdown
Collaborator

@bjcoombs bjcoombs commented Apr 6, 2026

Summary

  • Adds TenantScheduleEntity GORM model in services/control-plane/internal/scheduling/
  • Adds Atlas migration 20260406000001_create_tenant_schedule.sql creating the tenant_schedule table
  • Updates atlas.sum checksums

Changes Made

New entity: services/control-plane/internal/scheduling/entity.go

  • TenantScheduleEntity with fields: id, schedule_name, saga_name, cron_expr, enabled, manifest_version_id, metadata, created_at, updated_at
  • schedule_name has a unique constraint for idempotent manifest application
  • manifest_version_id is a soft cross-schema reference (no FK) for audit/debugging

New migration: 20260406000001_create_tenant_schedule.sql

  • Table lives in per-tenant schemas (schema-per-tenant architecture, no tenant_id column)
  • Indexes on enabled (for ScheduleProvider load) and saga_name (for manifest applier lookups)

Technical Details

  • CockroachDB compatible: no triggers, no expression indexes, no CONCURRENTLY, no partial indexes on new columns
  • manifest_version_id is intentionally a soft reference - cross-schema FK is not supported in CockroachDB's per-tenant schema pattern
  • metadata uses JSONB for extensibility without schema churn

Testing

  • go build ./services/control-plane/... passes
  • atlas migrate hash updated checksums successfully
  • Pre-commit checks pass (gofumpt, golangci-lint, gitleaks)

- Create TenantScheduleEntity GORM model in services/control-plane/internal/scheduling/
- Add Atlas migration 20260406000001_create_tenant_schedule.sql with schema, unique constraint on schedule_name, and indexes for enabled/saga_name lookups
- Update atlas.sum checksums

The tenant_schedule table lives in per-tenant schemas (schema-per-tenant architecture). manifest_version_id is a soft cross-schema reference with no FK constraint.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 6, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 5f00cf1f-4263-4992-b36a-a392f33356f8

📥 Commits

Reviewing files that changed from the base of the PR and between e5a0e2b and fea8fbe.

📒 Files selected for processing (1)
  • services/control-plane/internal/scheduling/entity_test.go
✅ Files skipped from review due to trivial changes (1)
  • services/control-plane/internal/scheduling/entity_test.go

📝 Walkthrough

Walkthrough

Adds a new tenant_schedule persistence model, a migration to create the tenant_schedule table, and unit tests for the entity, enabling storage of manifest-driven cron schedules with metadata and timestamps.

Changes

Cohort / File(s) Summary
Tenant Schedule Persistence
services/control-plane/internal/scheduling/entity.go, services/control-plane/migrations/20260406000001_create_tenant_schedule.sql
Introduces TenantScheduleEntity GORM model and a migration creating tenant_schedule with UUID primary key, schedule_name, saga_name, cron_expr, enabled (default TRUE), optional manifest_version_id, metadata JSONB, timestamps, unique constraint on schedule_name, and indexes on enabled and saga_name.
Entity Tests
services/control-plane/internal/scheduling/entity_test.go
Adds tests verifying TableName() and field population for TenantScheduleEntity instances.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and concisely describes the main change: adding a tenant_schedule database table for manifest-driven scheduling, which matches the core content of all three modified files.
Description check ✅ Passed The description is directly related to the changeset, providing clear details about the new GORM entity, migration, technical considerations, and testing approach that correspond to the actual changes made.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch per-tenant-scheduling--8--tenant-schedule-table

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@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 (2)
services/control-plane/migrations/20260406000001_create_tenant_schedule.sql (1)

12-12: Consider indexing manifest_version_id for audit/debug retrieval paths.

If you’ll trace schedules by manifest version during investigations or rollback analysis, this will avoid full scans as table size grows.

📌 Suggested migration addition
 CREATE INDEX idx_tenant_schedule_saga_name ON tenant_schedule (saga_name);
+CREATE INDEX idx_tenant_schedule_manifest_version_id ON tenant_schedule (manifest_version_id);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@services/control-plane/migrations/20260406000001_create_tenant_schedule.sql`
at line 12, Add a secondary index on manifest_version_id to speed lookups:
create an index on the tenant_schedule table for the manifest_version_id column
(use a CONCURRENTLY create if the table may already be large) so queries that
filter by manifest_version_id avoid full-table scans; update the migration to
include this index creation and a matching drop index in the rollback path.
services/control-plane/internal/scheduling/entity.go (1)

20-20: Consider using datatypes.JSON for consistency across other services, though control-plane currently uses *string for all JSONB fields.

While datatypes.JSON is objectively cleaner and avoids manual marshal/unmarshal, the control-plane service has established a deliberate pattern of using *string for JSONB fields (manifest repository also follows this). If the field requires structured access or deserialization, migration to datatypes.JSON would be an improvement; otherwise, maintaining consistency with the service's existing pattern is acceptable.

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

In `@services/control-plane/internal/scheduling/entity.go` at line 20, The
Metadata field in the struct currently uses *string for JSONB; change it to use
datatypes.JSON for consistency and easier structured access: update the Metadata
field's type to datatypes.JSON in the entity struct (symbol: Metadata) and add
the import for "gorm.io/datatypes", then adjust any code that assumes a *string
(marshal/unmarshal or nil checks) to handle datatypes.JSON accordingly (e.g.,
treat it as a byte slice or use datatypes.JSON.Marshal/Unmarshal where needed).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@services/control-plane/internal/scheduling/entity.go`:
- Line 20: The Metadata field in the struct currently uses *string for JSONB;
change it to use datatypes.JSON for consistency and easier structured access:
update the Metadata field's type to datatypes.JSON in the entity struct (symbol:
Metadata) and add the import for "gorm.io/datatypes", then adjust any code that
assumes a *string (marshal/unmarshal or nil checks) to handle datatypes.JSON
accordingly (e.g., treat it as a byte slice or use
datatypes.JSON.Marshal/Unmarshal where needed).

In `@services/control-plane/migrations/20260406000001_create_tenant_schedule.sql`:
- Line 12: Add a secondary index on manifest_version_id to speed lookups: create
an index on the tenant_schedule table for the manifest_version_id column (use a
CONCURRENTLY create if the table may already be large) so queries that filter by
manifest_version_id avoid full-table scans; update the migration to include this
index creation and a matching drop index in the rollback path.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 044c580e-2067-4284-ac1d-872c020ff8ec

📥 Commits

Reviewing files that changed from the base of the PR and between 31519f4 and e5a0e2b.

⛔ Files ignored due to path filters (1)
  • services/control-plane/migrations/atlas.sum is excluded by !**/*.sum
📒 Files selected for processing (2)
  • services/control-plane/internal/scheduling/entity.go
  • services/control-plane/migrations/20260406000001_create_tenant_schedule.sql

@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 6, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

Copy link
Copy Markdown

@claude claude Bot left a comment

Choose a reason for hiding this comment

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

See summary comment for details.

@claude
Copy link
Copy Markdown

claude Bot commented Apr 7, 2026

Claude Code Review

Commit: 669d6091 | CI: running (most checks pending, migration checksums verified)

Summary

Clean, well-scoped PR adding the tenant_schedule table for manifest-driven cron scheduling. Entity follows established patterns (staff, manifest entities), migration is CockroachDB-compatible, and atlas.sum is properly updated. The schema-per-tenant approach (no tenant_id column) is consistent with the project's multi-tenancy architecture.

Risk Assessment

Area Level Detail
Blast radius Low New table only, no existing code modified
Rollback Safe DROP TABLE reversal, no data in production yet
Scale Low Per-tenant schema keeps row counts small
Cross-system Low Soft reference to manifest_version_id, no FK constraints
Migration Safe CockroachDB compatible: no triggers, no expression indexes, no CONCURRENTLY, no partial indexes on new columns

Findings

Severity Location Description Status
Suggestion 20260406000001_create_tenant_schedule.sql:20 Boolean index on enabled has low selectivity; partial index (WHERE enabled = true) would be more efficient Open

Verification Checklist

  • Entity/migration column alignment: all 9 columns match in name, type, nullability, and constraints
  • GORM tags match DB schema (varchar lengths, uuid types, jsonb, timestamptz)
  • Unique constraint on schedule_name present in both entity and migration
  • autoCreateTime/autoUpdateTime GORM tags complement DB DEFAULT NOW()
  • updated_at has no auto-update trigger (expected -- CockroachDB has no triggers; GORM handles this in Go)
  • No bot review threads to evaluate

@bjcoombs bjcoombs merged commit a0c5ab4 into develop Apr 7, 2026
48 checks passed
@bjcoombs bjcoombs deleted the per-tenant-scheduling--8--tenant-schedule-table branch April 7, 2026 08:57
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.

1 participant