<@ULVA73B9P> help me design how i would use global...
# ask-marvin
r
@Marvin help me design how i would use global concurrency limits to have the following logic: 1) a total of 60 slots 2) there are 3 types of flows using the slots: A, B and C. 3) if a type of flow isnt queued, other flow types can use the slots that would be used by it, but if there are lots of jobs queued for flows A, B and C say, they can each only use 20 of the 60 slots
m
To achieve your desired concurrency logic in Prefect 3.x, you can use global concurrency limits. Here's a concise plan: 1. Define Global Concurrency Limit: Set a total concurrency limit of 60 slots for all flows combined. This ensures that no more than 60 flows run simultaneously across all types. 2. Define Per-Flow Type Limits: For each flow type (A, B, and C), set a concurrency limit of 20 slots. This means that if all three flow types have jobs queued, each can utilize up to 20 slots. 3. Dynamic Slot Allocation: If one flow type is not fully utilizing its 20 slots, the remaining slots can be used by other flow types. Prefect's concurrency management will handle this dynamic allocation based on the current demand and availability. 4. Slot Decay (Optional): You can configure slot decay to control how quickly slots become available again after being used. This is useful if you want to implement a "rate limiting" effect. For example, setting a
slot_decay_per_second
parameter can adjust how quickly slots refresh. For more detailed information on configuring these settings, you can refer to the Prefect documentation on global concurrency limits. If you need further details on the API or implementation specifics, you can explore Prefect's top-level API for additional functions and classes that might be useful.
r
@Marvin this doesn’t work. I mean like if there are no flow runs for B and C, A can use all 60 slots
m
To achieve the behavior where any flow type can use all available slots if others are not utilizing them, you need to configure a shared global concurrency limit without strictly partitioning slots for each flow type. Here's a refined approach: 1. Set a Global Concurrency Limit: Define a single global concurrency limit for all flows combined, with a total of 60 slots. 2. No Per-Flow Type Limits: Avoid setting strict limits for each flow type (A, B, C). Instead, allow any flow type to use the available slots up to the global limit. 3. Dynamic Allocation: This setup naturally allows any flow type to utilize all 60 slots if the others are not actively queuing tasks. Prefect will manage the allocation dynamically based on the current queue and demand. This configuration ensures that if flows B and C are not queuing, flow A can use all 60 slots, and vice versa. This requires managing the concurrency limits at the global level without subdividing them per flow type. For further details on configuring global concurrency limits, refer to the Prefect documentation on global concurrency limits.
r
@Marvin but if flow A queues 500 runs, and then B queues 10 runs, B doesn’t get to run in the slots flow A is “borrowing”
m
To prevent starvation and ensure fair distribution of slots among different flow types, you can use a combination of global concurrency limits and priority queueing. Here's a strategy you might consider: 1. Global Concurrency Limit: Set a global concurrency limit of 60 slots for all flows combined. 2. Priority Queueing: Implement priority levels for your flow types. Assign a priority to ensure that if a less-utilized flow (e.g., B or C) queues, it can take precedence over the more utilized flow (e.g., A) that is occupying more slots. 3. Dynamic Allocation with Priority: Use Prefect's priority queueing mechanism to dynamically allocate slots. This ensures that when a flow type like B queues runs, it gets a fair share of slots even if A has queued a large number of runs. For more information on priority queueing and managing concurrency, you can refer to the Prefect documentation on work pools and priorities. This setup allows you to balance the load dynamically and ensure that all flow types get a chance to execute without being blocked by a single, heavily queued flow type.