Skip to content

Commit 3ce5be1

Browse files
committed
feat(processor): fork event processing for rsources pipelines
1 parent a6e29f2 commit 3ce5be1

7 files changed

Lines changed: 813 additions & 3 deletions

File tree

processor/proc_fork.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,14 @@ func (proc *Handle) shouldForkDestination(destinationID string) bool {
5454
return enabled
5555
}
5656

57+
// forkableEvent reports whether the given event is eligible to be forked to the
58+
// intermediate (proc) jobsdb at all, independent of the per-destination
59+
// shouldForkDestination check. rsources (retl) jobs — those carrying a SourceJobRunID —
60+
// stay inline by default, unless configured otherwise.
61+
func (proc *Handle) forkableEvent(event *types.TransformerEvent) bool {
62+
return proc.config.forkRsourcesTrackedJobs || event.Metadata.SourceJobRunID == ""
63+
}
64+
5765
// newForkedJob builds a single intermediate (proc) job for one source event fanned out to
5866
// forkedDestIDs. The payload carries the source-level message + metadata (destination is
5967
// re-hydrated per consumer at drain time, see procRebuildStage), the forked destination

processor/proc_fork_test.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,31 @@ func TestShouldForkDestination(t *testing.T) {
5959
})
6060
}
6161

62+
func TestForkableEvent(t *testing.T) {
63+
retlEvent := &types.TransformerEvent{
64+
Metadata: types.Metadata{SourceJobRunID: "jr1"},
65+
}
66+
nonRetlEvent := &types.TransformerEvent{
67+
Metadata: types.Metadata{SourceJobRunID: ""},
68+
}
69+
70+
t.Run("rsources-tracked events stay inline by default", func(t *testing.T) {
71+
proc := newTestProcHandle()
72+
require.False(t, proc.config.forkRsourcesTrackedJobs)
73+
74+
require.False(t, proc.forkableEvent(retlEvent))
75+
require.True(t, proc.forkableEvent(nonRetlEvent))
76+
})
77+
78+
t.Run("rsources-tracked events fork once opted in", func(t *testing.T) {
79+
proc := newTestProcHandle()
80+
proc.config.forkRsourcesTrackedJobs = true
81+
82+
require.True(t, proc.forkableEvent(retlEvent))
83+
require.True(t, proc.forkableEvent(nonRetlEvent))
84+
})
85+
}
86+
6287
func TestNewForkedJob(t *testing.T) {
6388
proc := newTestProcHandle()
6489
event := &types.TransformerEvent{

processor/processor.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,7 @@ type Handle struct {
204204
pythonTransformConfig transformerutils.PythonTransformConfig
205205
userTransformationMirroringBlockedIDs config.ValueLoader[[]string]
206206
storeSamplerEnabled config.ValueLoader[bool]
207+
forkRsourcesTrackedJobs bool
207208
}
208209

209210
drainConfig struct {
@@ -827,6 +828,7 @@ func (proc *Handle) loadConfig() {
827828
// GWCustomVal is used as a key in the jobsDB customval column
828829
proc.config.GWCustomVal = proc.conf.GetStringVar("GW", "Gateway.CustomVal")
829830
proc.config.pythonTransformConfig = transformerutils.LoadPythonTransformConfig(proc.conf)
831+
proc.config.forkRsourcesTrackedJobs = proc.conf.GetBoolVar(false, "Processor.DestinationIsolation.forkRsourcesTrackedJobs")
830832
proc.loadReloadableConfig(defaultPayloadLimit, defaultMaxEventsToProcess)
831833
}
832834

@@ -2380,10 +2382,9 @@ func (proc *Handle) pretransformStage(partition string, preTrans *preTransformat
23802382
workspaceLibraries := proc.getWorkspaceLibraries(workspaceID)
23812383

23822384
// Destinations whose events are siphoned to the intermediate (proc) jobsdb
2383-
// rather than transformed inline. rsources (retl) jobs stay inline until the
2384-
// intermediate stage is modelled in rsources accounting.
2385+
// rather than transformed inline.
23852386
var forkedDestIDs []string
2386-
forkable := event.Metadata.SourceJobRunID == ""
2387+
forkable := proc.forkableEvent(event)
23872388
eventFanout := 0
23882389

23892390
for _, destType := range enabledDestTypes {
@@ -3003,6 +3004,9 @@ func (proc *Handle) storeStage(partition string, pipelineIndex int, in *storeMes
30033004
}
30043005
}
30053006
in.rsourcesStats.CollectStats(statusList)
3007+
// forkedJobs are only ever populated in the gw pool (the proc pool never re-forks),
3008+
// so this is a no-op when storeStage is invoked via procStoreStage.
3009+
in.rsourcesStats.JobsForked(in.forkedJobs)
30063010
statusDB := proc.statusUpdateDB(in)
30073011
commitStatuses := func(ctx context.Context) error {
30083012
return statusDB.WithUpdateSafeTx(ctx, func(tx jobsdb.UpdateSafeTx) error {

0 commit comments

Comments
 (0)