How to start workflow or await on results of a running one

I have a simple workflow that returns Google credentials. I want to ensure that only one of these workflows is running at the same time (user is asked once) but many other workflows can run it and await on the result of it.

It seems there is no way to subscribe on a running workflow. If I run it as Workflow.newChildWorkflowStub then it fails with an error that workflow WorkflowExecutionAlreadyStarted when there is a running one. Should I use some kind of proxy workflows or activities to get similar results. How would it look like?

class GetGoogleCredentialsWorkflowImpl : GetGoogleCredentialsWorkflow {
    private val userActivities = activities<UserActivities>()
    private var codesMap = mutableMapOf<Long, String>()

    // workflow method
    override fun getCredentials(userId: Long): GoogleCredentials? {
        val credentials: GoogleCredentials? = userActivities.getGoogleCredentials(userId)
        val now = Workflow.currentTimeMillis()
        return if (credentials == null || credentials.expired(now)) {
            userActivities.sendAuthorizationLinkToUser(userId)
            Workflow.await(Duration.ofHours(24)) { codesMap.containsKey(userId) }
            userActivities.processAuthorizationCode(userId, codesMap[userId]!!)
        } else {
            credentials
        }
    }

    // workflow signal
    override fun processCode(userId: Long, code: String) {
        codesMap[userId] = code
    }
}

We plan to add the ability to wait for an external workflow in the future. If the workflow is not long running you can wait using an activity. Another option is for the workflow to signal all waiting workflows before completion. This assumes that workflows register themselves through another signal.

Not sure what it takes to implement second scenario you described. how does it look like?

  1. WorkflowThatNeedsCredentials calls activity userActivities.requestGoogleCredentials(userId, workflowId). passing workflowId to send signal back.
  2. WorkflowThatNeedsCredentials implements reply signal processing and waits on reply
  3. userActivities.requestGoogleCredentials activity uses signalWithStart (we are using activity because can’t run signalWithStart from workflow)
  4. Implement GetGoogleCredentialsWorkflow.subscribe(workflowId: String) signal processing
  5. GetGoogleCredentialsWorkflow sends signal to all subscribers on return
1 Like

Yes, this is a precise representation of my proposal.