Skip to content

Fire TableTriggers when an upstream View is updated - #171

Merged
ryannedolan merged 2 commits into
mainfrom
view-triggers
Nov 7, 2025
Merged

ryannedolan merged 2 commits into
mainfrom
view-triggers

Conversation

@ryannedolan

@ryannedolan ryannedolan commented Nov 5, 2025

Copy link
Copy Markdown
Collaborator

Summary

  • Add .status.watermark to View objects.
  • Add ViewReconciler to detect changes to view watermarks.
  • Automatically fire TableTriggers when an upstream View is updated.

Details

In order to support jobs that listen to multiple tables, we have a few options:

  1. Make breaking changes to TableTrigger. Instead of one table, listen to an array of tables.
  2. Add a second Trigger type that supports multiple tables. Maybe call it MultiTableTrigger.
  3. Leverage View, which supports an arbitrary number of source tables.

This PR implements option 3, which is probably the least obvious. The motivation here is to mimic traditional CREATE TRIGGER DDL, e.g. as supported by Oracle, which works with either tables or views but not lists of tables. In typical DDL, you must first CREATE VIEW FOO and then CREATE TRIGGER BAR ON FOO. This means the trigger has a single object to listen to (the view object) rather than a list of objects.

In order to support this pattern, I've added a new ViewRconciler which monitors .status.watermark and fires any listening TableTriggers. Batch-oriented jobs that materialize a view can update the view's watermark to trigger downstream jobs. Stream-oriented jobs can do the same whenever they checkpoint.

Testing Done

New unit test passes:

Reconciling request Request{name='view-1', namespace='namespace'}
View view-1 was updated at 2025-11-06T14:10:11.309811-06:00.
Firing downstream trigger table-trigger.

@ryannedolan
ryannedolan marked this pull request as ready for review November 6, 2025 17:17
yamlApi.createWithAnnotationsAndLabels(yaml, annotations, labels);
}

private V1alpha1View getView(V1alpha1TableTrigger trigger) throws SQLException {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Is the correlation between objects, in terms of ownership still
View -> Pipeline -> Trigger?

It seems odd to now have a link from the Trigger back to the View

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

The View here isn't necessarily the same View as in your example. In the typical View->Pipeline->Trigger situation, the Trigger likely listens to one of the source tables in the View, not the View itself. Or, the Trigger may listen to an upstream View, if you have a views-of-views situation.

I'm planning to add a CREATE TRIGGER DDL along these lines:

CREATE MATERIALIZED VIEW FOO AS SELECT a, b FROM T;
CREATE TRIGGER BAR ON FOO AS 'my-job-template';

In this case, the CREATE...VIEW may result in Triggers, but they would listen to specific tables, not views. The CREATE TRIGGER would create a new Trigger that is wired up to listen to the View object, rather than a set of physical tables. Both leverage JobTemplates and TableTriggers under the hood, but in slightly different ways.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Great, this makes sense. Seems pretty powerful too, seems like we can define multiple triggers on the same view that may do different things at different cadences or whatnot as we expand the trigger feature set.

@ryannedolan
ryannedolan marked this pull request as draft November 6, 2025 18:13
@@ -36,6 +36,14 @@ spec:
table:

@srnand srnand Nov 6, 2025

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The table field is currently a required property in this CRD. Now that the view will have its own reconciler, which will handle updates and subsequently update the trigger timestamp in the table trigger object, do we still need the viewRef?

Instead, we could introduce a breaking change by renaming the table property to something more generic, such as source, which could represent either a single table or a view.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I thought of that, but a view is technically a kind of table (especially if it's materialized), so I think it's reasonable to reuse table here.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

yep, that works! I was mainly thinking that we don’t need a separate view ref.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Yeah I'm going to drop the viewRef and use a label instead. That way the new ViewReconciler can fire any TableTriggers that have a matching view label.

@ryannedolan
ryannedolan force-pushed the view-triggers branch 2 times, most recently from 2669faa to 0b0a326 Compare November 6, 2025 20:10
@ryannedolan
ryannedolan marked this pull request as ready for review November 6, 2025 20:19

@srnand srnand left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

looks like one of the integration tests failed ? otherwise lgtm

V1alpha1ViewStatus status = object.getStatus();
if (status != null && status.getWatermark() != null) {
log.info("View {} was updated at {}.", name, status.getWatermark());
for (V1alpha1TableTrigger trigger : tableTriggerApi.select(VIEW_KEY + "=" + name)) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I imagine this view label will be added by the CREATE TRIGGER statement, right?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

yes that's the plan

@jogrogan jogrogan left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM

@ryannedolan
ryannedolan enabled auto-merge (squash) November 7, 2025 15:48
@ryannedolan
ryannedolan merged commit 87a82dc into main Nov 7, 2025
1 check passed
@ryannedolan
ryannedolan deleted the view-triggers branch November 7, 2025 16:01
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.

3 participants