2

I have a Google Assistant action with fulfilment through Firebase Cloud Functions. I understand that Cloud Functions may share instances between invocations, and that you can use the Global scope to do heavy lifting and preparation. My function instantiates a global class that has serialised some JSON and handles returning data and other tasks in my function. I have variables in this class that are set when the function is called, and I have been careful to make sure that the variables are all set using the conv.data session data object that is unique to the current conversation. The hope is that although the class instance may exist between different invocations, and possibly by different users, it will still be contextualised to the local scope, and I wont see any variables being overwritten by other sessions.

Which brings me to the question, which is, how can I test this? I have tried to test on my mobile device using the Google Assistant app, at the same time as testing in the browser console. I witnessed the two sessions getting merged together, and it was an unholy mess, but I am not sure if that was the global scope, or just that I was testing two sessions with the same user account.

Can anyone enlighten me on whether it is possible to run two of the same action using the same user account? It looked like the conv.data object had a mix of the two different sessions I was running which suggests it was using the same conversation token for both sessions.

Another question would be, do you think using a global class to store state across invocations is going to be an issue with different users? The docs do state that only one invocation of the function can ever happen at a time. So there shouldn't be any race condition type scenarios.

Prisoner
  • 49,922
  • 7
  • 53
  • 105
Lee Probert
  • 10,308
  • 8
  • 43
  • 70

1 Answers1

2

Dialogflow should keep the data in conv.data isolated to a single session, even sessions from the same user. When you're using Dialogflow, this data is stored in a Context, which is session specific.

You can verify this by turning StackDriver logging on, which will let you examine the exact request and response that Dialogflow is using with your fulfillment, and this will include the session ID for tracking. (And if you think it is mixing the two, posting the request and response details would help figure out what is going on.)

Very roughly, it sounds like you're getting something mixed into your global, or possibly something set in one session that isn't cleared or overwritten by a different one. Again - seeing the exact requests and responses should help you (and/or us) figure that out.

My attitude is that a global such as this should be treated as read-only. If you want to have some environment object that contains the relevant information for just this session - I'd keep that separate, just from a philosophical design.

Certainly I wouldn't use this global state to store information between sessions. While a function will only be invoked, I'm not sure how that would work with Promises - which you'll need once you start any async operations. It also runs the risk that subsequent invocations might be on different instances.

My approach, in short, (which I make pretty firm in multivocal):

  • Store all state in a Context (which conv.data should so).
  • Access this via the request, conv, or some other request-specific object that you create.
  • Global information / configuration should be read-only.
Prisoner
  • 49,922
  • 7
  • 53
  • 105
  • you say `The data in conv.data shouldn't be mixed between sessions` but the docs state that you should use `conv.data` to store data across the conversation. This is how I am managing state atm. My global class _is_ being written to but I do it on every invocation so it is working with information that is only relevant to that session. I basically pass in the properties of `conv.data` into the class at every step, so it can do its logic and build the response object I need to return. – Lee Probert Mar 12 '20 at 11:11
  • btw, really appreciate you taking the time to respond to me. It's really hard to get sound advice on this stuff. – Lee Probert Mar 12 '20 at 11:51
  • Sorry, I may have been a bit unclear in what I said, and I've edited things a bit to be more clear. `conv.data` shouldn't be mixing things up, which suggests something is going on with your global. but if you think it is - there is some debugging which we can help you with to see. – Prisoner Mar 12 '20 at 22:12
  • It has been working. We have tried concurrent testing and the global class refreshing itself at every step with the `conv.data` seems to be working fine. – Lee Probert Mar 13 '20 at 16:09