Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Return early if no pipelines found #1614

Open
FelixTing opened this issue Sep 11, 2024 · 0 comments
Open

Return early if no pipelines found #1614

FelixTing opened this issue Sep 11, 2024 · 0 comments

Comments

@FelixTing
Copy link
Member

// MessageReceived provides runtime orchestration to pass the envelope / context to configured pipeline(s) along with a response callback to execute on each completion.
func (mp *triggerMessageProcessor) MessageReceived(ctx interfaces.AppFunctionContext, envelope types.MessageEnvelope, responseHandler interfaces.PipelineResponseHandler) error {
mp.messagesReceived.Inc(1)
lc := mp.serviceBinding.LoggingClient()
lc.Debugf("trigger attempting to find pipeline(s) for topic %s", envelope.ReceivedTopic)
// ensure we have a context established that we can safely cast to *appfunction.Context to pass to runtime
if _, ok := ctx.(*appfunction.Context); ctx == nil || !ok {
ctx = mp.serviceBinding.BuildContext(envelope)
}
pipelines := mp.serviceBinding.GetMatchingPipelines(envelope.ReceivedTopic)
lc.Debugf("trigger found %d pipeline(s) that match the incoming topic '%s'", len(pipelines), envelope.ReceivedTopic)
var finalErr error
errorCollectionLock := sync.RWMutex{}
pipelinesWaitGroup := sync.WaitGroup{}
appContext, ok := ctx.(*appfunction.Context)
if !ok {
return fmt.Errorf("context received was not *appfunction.Context (%T)", ctx)
}
targetData, err, isInvalidMessage := mp.serviceBinding.DecodeMessage(appContext, envelope)
if err != nil {
if isInvalidMessage {
mp.invalidMessagesReceived.Inc(1)
}
return fmt.Errorf("unable to decode message: %s", err.Err.Error())
}
for _, pipeline := range pipelines {
pipelinesWaitGroup.Add(1)
pipeline.MessagesProcessed.Inc(1)
go func(p *interfaces.FunctionPipeline, wg *sync.WaitGroup, errCollector func(error)) {
startedAt := time.Now()
defer p.MessageProcessingTime.UpdateSince(startedAt)
defer wg.Done()
lc.Debugf("trigger sending message to pipeline %s (%s)", p.Id, envelope.CorrelationID)
childCtx, ok := ctx.Clone().(*appfunction.Context)
if !ok {
errCollector(fmt.Errorf("context received was not *appfunction.Context (%T)", childCtx))
return
}
if msgErr := mp.serviceBinding.ProcessMessage(childCtx, targetData, p); msgErr != nil {
lc.Errorf("message error in pipeline %s (%s): %s", p.Id, envelope.CorrelationID, msgErr.Err.Error())
errCollector(msgErr.Err)
} else {
if responseHandler != nil {
if outputErr := responseHandler(childCtx, p); outputErr != nil {
lc.Errorf("failed to process output for message '%s' on pipeline %s: %s", ctx.CorrelationID(), p.Id, outputErr.Error())
errCollector(outputErr)
return
}
}
lc.Debugf("trigger successfully processed message '%s' in pipeline %s", p.Id, envelope.CorrelationID)
}
}(pipeline, &pipelinesWaitGroup, func(e error) {
errorCollectionLock.Lock()
defer errorCollectionLock.Unlock()
finalErr = multierror.Append(finalErr, e)
})
}
pipelinesWaitGroup.Wait()
return finalErr
}

In the method MssageReceived within the ‎triggerMessageProcessor implementation, if no pipelines are found for the received topic, it would be more efficient to return early to avoid unnecessary allocations, message decoding, and WaitGroup usage.

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

No branches or pull requests

1 participant