Skip to content
Merged
Show file tree
Hide file tree
Changes from 34 commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
010f3ea
Implement IntermediateCatchEventBuilder
IceS2 Mar 4, 2026
9403129
Implement IntermediateCatchEventBuilder
IceS2 Mar 4, 2026
53ced59
Implement ManualTask workflow node
IceS2 Mar 16, 2026
aed3969
Simplify BaseDelegate: remove shared Expression fields
IceS2 Mar 16, 2026
77d0d61
Update generated TypeScript types
github-actions[bot] Mar 16, 2026
909f2d2
Fix CloseTaskImpl resolution bug and rename taskCreated variable
IceS2 Mar 16, 2026
bb29b37
Merge branch 'feat/incident-lifecycle-workflow' into feat/ilw-pr2-man…
IceS2 Mar 18, 2026
0ab66d0
Address PR review: configurable assignees, null-guard, required fields
IceS2 Mar 20, 2026
1a5c2b8
Update generated TypeScript types
github-actions[bot] Mar 20, 2026
a5020bc
fix: safe boolean cast and dedup assignees in resolveAssignees
IceS2 Mar 23, 2026
6f9712d
Add Task-Workflow bridge with async retry
IceS2 Mar 16, 2026
57d2080
Address code review findings on Task-Workflow bridge
IceS2 Mar 16, 2026
aa52ef1
feat(outbox): add task_workflow_outbox table migrations
IceS2 Mar 19, 2026
5e78598
feat(outbox): add OutboxEntry POJO and TaskWorkflowOutboxDAO
IceS2 Mar 19, 2026
f431868
feat(outbox): add TaskWorkflowOutboxDrainer with unit tests
IceS2 Mar 19, 2026
443f8cd
feat(outbox): route task status events through outbox in WorkflowEven…
IceS2 Mar 19, 2026
7d39894
test(outbox): add consumer routing filter tests
IceS2 Mar 19, 2026
60849c2
refactor(outbox): remove direct postUpdate hook and retry infrastructure
IceS2 Mar 19, 2026
b2df46b
feat(outbox): wire TaskWorkflowOutboxDrainer lifecycle into WorkflowH…
IceS2 Mar 19, 2026
4cb3ed6
test(outbox): increase ManualTaskWorkflowTest timeouts for polling la…
IceS2 Mar 19, 2026
521d2f4
fix(outbox): wrap enqueueTaskMessage in try-catch to prevent signal b…
IceS2 Mar 19, 2026
35205ef
fix(outbox): rename index prefix from idx_two_ to idx_outbox_ for cla…
IceS2 Mar 19, 2026
6d0d47c
fix(outbox): prevent out-of-order delivery when another worker holds …
IceS2 Mar 20, 2026
9b6f50b
perf(outbox): replace 1+3N queries with single bulk query per drain c…
IceS2 Mar 20, 2026
b9e24c7
fix(outbox): address review findings — C2, C3, I2, I3, I4, I5
IceS2 Mar 20, 2026
926787c
fix(outbox): add batch limit and prioritized ordering to drain query
IceS2 Mar 20, 2026
17f09d5
test(outbox): replace ManualTaskWorkflowTest with lean E2E ManualTask…
IceS2 Mar 20, 2026
f73830b
fix(outbox): handle raw string FieldChange.newValue in enqueueTaskMes…
IceS2 Mar 20, 2026
56ec631
style: spotless formatting on IncidentTaskIntegrationIT
IceS2 Mar 20, 2026
b5512e0
fix(outbox): wrap enqueue retry exhaustion in EventPublisherException
IceS2 Mar 20, 2026
b001e36
fix(outbox): null createdBy fallback, exhausted cleanup, idempotent e…
IceS2 Mar 20, 2026
f7a40dc
fix(outbox): use INSERT IGNORE / ON CONFLICT DO NOTHING for idempoten…
IceS2 Mar 20, 2026
82c23fa
feat(incident): add IncidentTcrsSyncHandler for Task→TCRS sync
IceS2 Mar 25, 2026
46bdff2
Update generated TypeScript types
github-actions[bot] Mar 25, 2026
0b494af
fix(manualTask): address PR review — assignees as EntityLinks, termin…
IceS2 Mar 25, 2026
5380b1b
Merge branch 'feat/ilw-pr2-manual-task-node' into feat/ilw-pr3-task-w…
IceS2 Mar 25, 2026
ea7a316
Merge branch 'feat/ilw-pr3-task-workflow-bridge' into feat/ilw-item2-…
IceS2 Mar 25, 2026
0bc1464
Merge branch 'feat/ilw-item2-incident-tcrs-sync-hook' of github.com:o…
IceS2 Mar 25, 2026
5386602
Update generated TypeScript types
github-actions[bot] Mar 25, 2026
a3df3e2
Merge branch 'feat/incident-lifecycle-workflow' into feat/ilw-item2-i…
IceS2 Mar 30, 2026
f9e2a6e
fix: address PR review — rename methods, guard extractStringValue, op…
IceS2 Mar 31, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions bootstrap/sql/migrations/native/2.0.0/mysql/schemaChanges.sql
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ CREATE TABLE IF NOT EXISTS task_entity (
KEY idx_status_about (status, aboutFqnHash)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

-- aboutEntityLink: hierarchical entity identity for lifecycle handler lookups
ALTER TABLE task_entity ADD COLUMN IF NOT EXISTS aboutEntityLink varchar(1024)
GENERATED ALWAYS AS (json_unquote(json_extract(`json`, _utf8mb4'$.aboutEntityLink'))) STORED;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

is mysql not utf8 by default?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I think it should be, but it does not hurt to be defensive, right?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

In sql files okay, in run time for other cases when we know the value is so and so, it's better to code that way rather than being defensive, makes debugging a pain. As this is in sql file, it's okay!

CREATE INDEX idx_task_about_entity_link ON task_entity (aboutEntityLink(255));

CREATE TABLE IF NOT EXISTS new_task_sequence (
id bigint NOT NULL DEFAULT 0
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
Expand Down Expand Up @@ -86,3 +91,24 @@ CREATE TABLE IF NOT EXISTS activity_stream_config (
KEY idx_scope (scope),
KEY idx_enabled (enabled)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

-- Add stageResult generated column to workflow_instance_state_time_series
ALTER TABLE workflow_instance_state_time_series
ADD COLUMN stageResult VARCHAR(256) GENERATED ALWAYS AS (json_unquote(json_extract(json, '$.stage.result'))) STORED NULL;

-- Task Workflow Outbox - Transactional outbox for ManualTask message delivery
-- Messages are enqueued by WorkflowEventConsumer and drained by TaskWorkflowOutboxDrainer
CREATE TABLE IF NOT EXISTS task_workflow_outbox (
id VARCHAR(36) NOT NULL,
taskId VARCHAR(36) NOT NULL,
status VARCHAR(64) NOT NULL,
updatedBy VARCHAR(256),
createdAt BIGINT NOT NULL,
delivered TINYINT(1) NOT NULL DEFAULT 0,
attempts INT NOT NULL DEFAULT 0,
lastAttemptAt BIGINT,
PRIMARY KEY (id),
INDEX idx_outbox_pending (delivered, createdAt),
INDEX idx_outbox_pending_tasks (delivered, taskId),
INDEX idx_outbox_task_order (taskId, delivered, createdAt)
);
26 changes: 26 additions & 0 deletions bootstrap/sql/migrations/native/2.0.0/postgres/schemaChanges.sql
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ CREATE INDEX IF NOT EXISTS idx_task_status_category ON task_entity (status, cate
CREATE INDEX IF NOT EXISTS idx_task_about_fqn_hash ON task_entity (aboutfqnhash);
CREATE INDEX IF NOT EXISTS idx_task_status_about ON task_entity (status, aboutfqnhash);

-- aboutEntityLink: hierarchical entity identity for lifecycle handler lookups
ALTER TABLE task_entity ADD COLUMN IF NOT EXISTS aboutentitylink character varying(1024)
GENERATED ALWAYS AS ((json ->> 'aboutEntityLink'::text)) STORED;
CREATE INDEX IF NOT EXISTS idx_task_about_entity_link ON task_entity (aboutentitylink);

CREATE TABLE IF NOT EXISTS new_task_sequence (
id bigint NOT NULL DEFAULT 0
);
Expand Down Expand Up @@ -89,3 +94,24 @@ CREATE TABLE IF NOT EXISTS activity_stream_config (

CREATE INDEX IF NOT EXISTS idx_activity_config_scope ON activity_stream_config (scope);
CREATE INDEX IF NOT EXISTS idx_activity_config_enabled ON activity_stream_config (enabled);

-- Add stageResult generated column to workflow_instance_state_time_series
ALTER TABLE workflow_instance_state_time_series
ADD COLUMN stageResult VARCHAR(256) GENERATED ALWAYS AS (json -> 'stage' ->> 'result') STORED;

-- Task Workflow Outbox - Transactional outbox for ManualTask message delivery
CREATE TABLE IF NOT EXISTS task_workflow_outbox (
id character varying(36) NOT NULL,
taskId character varying(36) NOT NULL,
status character varying(64) NOT NULL,
updatedBy character varying(256),
createdAt bigint NOT NULL,
delivered boolean NOT NULL DEFAULT FALSE,
attempts integer NOT NULL DEFAULT 0,
lastAttemptAt bigint,
PRIMARY KEY (id)
);

CREATE INDEX IF NOT EXISTS idx_outbox_pending ON task_workflow_outbox (delivered, createdAt);
CREATE INDEX IF NOT EXISTS idx_outbox_pending_tasks ON task_workflow_outbox (delivered, taskId);
CREATE INDEX IF NOT EXISTS idx_outbox_task_order ON task_workflow_outbox (taskId, delivered, createdAt);
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,8 @@ void testFullIncidentWorkflow_NewToAckToAssignedToResolved(TestNamespace ns) {
String id = ns.shortPrefix();
DatabaseService service = DatabaseServiceTestFactory.createPostgresWithName("svc" + id, ns);
DatabaseSchema schema = DatabaseSchemaTestFactory.createSimpleWithName("sch" + id, ns, service);
Table table = TableTestFactory.createSimpleWithName("tbl" + id, ns, schema.getFullyQualifiedName());
Table table =
TableTestFactory.createSimpleWithName("tbl" + id, ns, schema.getFullyQualifiedName());

TestCase testCase =
TestCaseBuilder.create(client)
Expand Down Expand Up @@ -170,7 +171,8 @@ void testIncidentAck_CreatesTaskWithCorrectCategory(TestNamespace ns) {
String id = ns.shortPrefix();
DatabaseService service = DatabaseServiceTestFactory.createPostgresWithName("sv" + id, ns);
DatabaseSchema schema = DatabaseSchemaTestFactory.createSimpleWithName("sc" + id, ns, service);
Table table = TableTestFactory.createSimpleWithName("tb" + id, ns, schema.getFullyQualifiedName());
Table table =
TableTestFactory.createSimpleWithName("tb" + id, ns, schema.getFullyQualifiedName());

TestCase testCase =
TestCaseBuilder.create(client)
Expand Down Expand Up @@ -212,7 +214,8 @@ void testDirectAssignment_NewToAssigned(TestNamespace ns) {
String id = ns.shortPrefix();
DatabaseService service = DatabaseServiceTestFactory.createPostgresWithName("s" + id, ns);
DatabaseSchema schema = DatabaseSchemaTestFactory.createSimpleWithName("c" + id, ns, service);
Table table = TableTestFactory.createSimpleWithName("t" + id, ns, schema.getFullyQualifiedName());
Table table =
TableTestFactory.createSimpleWithName("t" + id, ns, schema.getFullyQualifiedName());

TestCase testCase =
TestCaseBuilder.create(client)
Expand Down Expand Up @@ -254,7 +257,8 @@ void testReassignment_AssignedToAssigned(TestNamespace ns) {
String id = ns.shortPrefix();
DatabaseService service = DatabaseServiceTestFactory.createPostgresWithName("a" + id, ns);
DatabaseSchema schema = DatabaseSchemaTestFactory.createSimpleWithName("b" + id, ns, service);
Table table = TableTestFactory.createSimpleWithName("c" + id, ns, schema.getFullyQualifiedName());
Table table =
TableTestFactory.createSimpleWithName("c" + id, ns, schema.getFullyQualifiedName());

TestCase testCase =
TestCaseBuilder.create(client)
Expand Down Expand Up @@ -309,7 +313,8 @@ void testDirectResolution_NewToResolved_NoTaskCreated(TestNamespace ns) {
String id = ns.shortPrefix();
DatabaseService service = DatabaseServiceTestFactory.createPostgresWithName("e" + id, ns);
DatabaseSchema schema = DatabaseSchemaTestFactory.createSimpleWithName("f" + id, ns, service);
Table table = TableTestFactory.createSimpleWithName("g" + id, ns, schema.getFullyQualifiedName());
Table table =
TableTestFactory.createSimpleWithName("g" + id, ns, schema.getFullyQualifiedName());

TestCase testCase =
TestCaseBuilder.create(client)
Expand Down Expand Up @@ -350,7 +355,8 @@ void testTaskPayload_ContainsTestCaseResolutionStatusId(TestNamespace ns) {
String id = ns.shortPrefix();
DatabaseService service = DatabaseServiceTestFactory.createPostgresWithName("i" + id, ns);
DatabaseSchema schema = DatabaseSchemaTestFactory.createSimpleWithName("j" + id, ns, service);
Table table = TableTestFactory.createSimpleWithName("k" + id, ns, schema.getFullyQualifiedName());
Table table =
TableTestFactory.createSimpleWithName("k" + id, ns, schema.getFullyQualifiedName());

TestCase testCase =
TestCaseBuilder.create(client)
Expand Down Expand Up @@ -394,7 +400,8 @@ void testMultipleIncidents_IndependentTasks(TestNamespace ns) {
String id = ns.shortPrefix();
DatabaseService service = DatabaseServiceTestFactory.createPostgresWithName("m" + id, ns);
DatabaseSchema schema = DatabaseSchemaTestFactory.createSimpleWithName("n" + id, ns, service);
Table table = TableTestFactory.createSimpleWithName("o" + id, ns, schema.getFullyQualifiedName());
Table table =
TableTestFactory.createSimpleWithName("o" + id, ns, schema.getFullyQualifiedName());

String id1 = ns.uniqueShortId();
String id2 = ns.uniqueShortId();
Expand Down Expand Up @@ -461,7 +468,8 @@ void testIncidentTaskListByCategory(TestNamespace ns) {
String id = ns.shortPrefix();
DatabaseService service = DatabaseServiceTestFactory.createPostgresWithName("r" + id, ns);
DatabaseSchema schema = DatabaseSchemaTestFactory.createSimpleWithName("s" + id, ns, service);
Table table = TableTestFactory.createSimpleWithName("t" + id, ns, schema.getFullyQualifiedName());
Table table =
TableTestFactory.createSimpleWithName("t" + id, ns, schema.getFullyQualifiedName());

TestCase testCase =
TestCaseBuilder.create(client)
Expand Down
Loading