@@ -167,9 +167,18 @@ func (proc *Handle) procStoreStage(partition string, pipelineIndex int, in *stor
167167// re-hydrates Destination/Connection/Libraries/Credentials from live backendConfig.
168168// Dest-filter and consent are NOT re-applied here — they were already decided in gw
169169// pool (preprocess/fan-out) and the proc job is only stored for the destinations that
170- // passed them. A destination deleted/disabled between fan-out and consume is dropped
171- // gracefully to a terminal status. Surviving events are grouped per (source,destination)
172- // so the reused transform stages operate on them unchanged.
170+ // passed them.
171+ //
172+ // Config drift between fan-out and consume: a destination deleted from the config
173+ // cannot be re-hydrated (its type and config are gone, so there isn't even a router
174+ // queue to store to) and is dropped to a terminal status. A destination merely
175+ // disabled keeps flowing through the pipeline so it reaches the router/batchrouter
176+ // queue and is aborted there with the usual drain reporting — DESTINATION_ENTER was
177+ // already recorded at fan-out, so dropping here would leave the reporting chain
178+ // dangling. Processor.DestinationIsolation.dropEventsForDisabledDestAtProcRebuild opts back
179+ // into dropping disabled destinations here, e.g. to drain a proc-table backlog quickly
180+ // after the user disables a misbehaving destination. Surviving events are grouped per
181+ // (source,destination) so the reused transform stages operate on them unchanged.
173182func (proc * Handle ) procRebuildStage (destinationID string , in subJob ) (* transformationMessage , error ) { //nolint: unparam
174183 s := time .Now ()
175184 defer func () {
@@ -183,6 +192,7 @@ func (proc *Handle) procRebuildStage(destinationID string, in subJob) (*transfor
183192 statusList := make ([]* jobsdb.JobStatusT , 0 , len (in .subJobs ))
184193 var reportMetrics []* reportingtypes.PUReportedMetric
185194 var totalEvents int
195+ dropDisabled := proc .config .dropEventsForDisabledDestAtProcRebuild .Load ()
186196
187197 for _ , job := range in .subJobs {
188198 var payload procJobPayload
@@ -194,11 +204,17 @@ func (proc *Handle) procRebuildStage(destinationID string, in subJob) (*transfor
194204 totalEvents ++
195205 sourceID := payload .Metadata .SourceID
196206
197- // Hydrate the destination from live config. Config drift: a destination
198- // deleted/disabled since fan-out is dropped gracefully to a terminal status.
199- dest , ok := proc .getEnabledDestinationByID (sourceID , destinationID )
207+ // Re-hydrate the destination from live config. Config drift: a destination
208+ // deleted since fan-out cannot be re-hydrated and is dropped to a terminal
209+ // status; a disabled one keeps flowing (aborted with reporting at the
210+ // router/batchrouter) unless dropEventsForDisabledDestAtProcRebuild is set.
211+ dest , ok := proc .getDestinationByID (sourceID , destinationID )
200212 if ! ok {
201- statusList = append (statusList , procJobStatus (job , destinationID , jobsdb .Filtered .State , `{"reason":"destination not found or disabled"}` ))
213+ statusList = append (statusList , procJobStatus (job , destinationID , jobsdb .Filtered .State , `{"reason":"destination not found"}` ))
214+ continue
215+ }
216+ if ! dest .Enabled && dropDisabled {
217+ statusList = append (statusList , procJobStatus (job , destinationID , jobsdb .Filtered .State , `{"reason":"destination disabled"}` ))
202218 continue
203219 }
204220
@@ -259,14 +275,14 @@ func (proc *Handle) procRebuildStage(destinationID string, in subJob) (*transfor
259275 }, nil
260276}
261277
262- // getEnabledDestinationByID returns the live, enabled destination for the given
263- // (source, destination) connection, or false when it no longer exists / is disabled .
264- func (proc * Handle ) getEnabledDestinationByID (sourceID , destinationID string ) (backendconfig.DestinationT , bool ) {
278+ // getDestinationByID returns the live destination for the given (source, destination)
279+ // connection — enabled or not — or false when it no longer exists in the config .
280+ func (proc * Handle ) getDestinationByID (sourceID , destinationID string ) (backendconfig.DestinationT , bool ) {
265281 proc .config .configSubscriberLock .RLock ()
266282 defer proc .config .configSubscriberLock .RUnlock ()
267283 for i := range proc .config .sourceIdDestinationMap [sourceID ] {
268284 dest := & proc .config .sourceIdDestinationMap [sourceID ][i ]
269- if dest .ID == destinationID && dest . Enabled {
285+ if dest .ID == destinationID {
270286 return * dest , true
271287 }
272288 }
0 commit comments