Bekaert integration services may receive messages that fail temporarily during asynchronous processing. Implement a queue-based processor that retries failed messages up to a fixed limit and sends messages that still fail to a dead-letter list.
A deterministic failure_plan simulates the message handler. For a message ID, a non-negative value indicates how many initial attempts fail before processing succeeds. A value of -1 indicates a permanent failure. Messages are processed from a FIFO queue, and each retry is appended to the queue so other pending messages can be handled first.
Implement process_messages(messages, max_retries, failure_plan):
messages is a list of dictionaries, each containing a unique string id and any payload fields.max_retries is a non-negative integer. A message may be attempted at most max_retries + 1 times.failure_plan is a dictionary mapping message IDs to failure counts. IDs absent from the dictionary succeed immediately.processed, dead_letter, and attempts keys. processed and dead_letter contain IDs in the order they finish. attempts maps every ID to its total number of attempts.def process_messages(messages, max_retries, failure_plan):