Summarizing your requirements:
- Trigger workflow executions with Pub/Sub messages
- Execute at most 3 workflow executions concurrently
- Queue up waiting Pub/Sub messages
- (Unspecified) Do you need messages processed in the order delivered?
There is no out-of-the box capability to achieve this. For fun, below is a solution that doesn't need secondary compute (and therefore is still fully managed).
The key to making this work is likely starting new executions for every message, but waiting in that execution if needed. Workflows does not provide a global concurrency construct, so you'll need to use some external storage, such as Firestore. An algorithm like this could work:
- Create a callback
- Push the callback into a FIFO queue
- Atomically increment a counter (which returns the new value)
- If the returned value is <= 3, pop the last callback and call it
- Wait on the callback
- -- MAIN WORKFLOW HERE --
- Atomically decrement the counter
- If the returned value is < 3, pop the last callback and call it
To keep things cleaner, you could put the above steps in a the triggered workflow and the main logic in a separate workflow that is called as needed.