Search code examples
pythonazure-functionsazureservicebus

How to defer input message within a Service Bus Trigger in Python?


I want to defer the input message of a Service Bus Trigger, since the message should only be marked as complete when another Service Bus Trigger finishes. However, the only example of message deferral in Python I've found uses a queue receiver (example from Azure documentation). If I understand correctly, I cannot get the message via such receiver within the trigger, since the input message is locked by the trigger.

I found a post where apparently there is a way to do this in C#, but nothing in Python.

Is there a way to do this?

Here's the code of the trigger to illustrate what I would like to do:

import azure.functions as func
import logging

from typing import List

 from __app__.config import config
 from azure.servicebus import (
     ServiceBusClient,
     ServiceBusReceiver,
     NEXT_AVAILABLE_SESSION,
     ServiceBusReceivedMessage,
 )

def main(msg: func.ServiceBusMessage):
    logging.info(
        f"complete-message test service bus trigger receives {msg.message_id=}, {msg.sequence_number=}"
    )

    service_bus_client = ServiceBusClient.from_connection_string(
         conn_str="conn_string"
     )
 
    queue_receiver: ServiceBusReceiver = service_bus_client.get_queue_receiver(
         queue_name="test-queue",
         session_id=NEXT_AVAILABLE_SESSION,
         prefetch=5,
     )

    # This does not work since defer_message expects a ServiceBusReceivedMessage, not a ServiceBusMessage
    # queue_receiver.defer_message(message=msg)

    # This call does not return any message, which makes sense since the message is locked by the trigger
    messages: List[ServiceBusReceivedMessage] = queue_receiver.receive_messages(
            max_wait_time=3
        )

Solution

  • The short version is - this can't be done from Python, other language workers, or isolated process Functions at this time.

    Only the in-process model for .NET has the ability to perform explicit message completion operations. Because the Function code shares the same process with the trigger itself, it is able to invoke operations on the underlying Service Bus clients used by the trigger and isn't blocked by a process boundary.

    This is something that is being investigated for the isolated process model - which includes workers for non-.NET languages. It requires a fairly extensive set of enhancements to the Functions host and runtime to enable an RPC channel so that worker processes can participate in request/response-style communication with the host and, by extension, triggers and output bindings. At present, there's no timeframe that can be shared for when we may see this.