0

I am reading data from my Firebase realtime database from Java code running inside a GCP Cloud Function. I am using the Admin SDK for this purpose. I am following this Google documentation page very closely.

The only approach available for Java is to attach an asynchronous callback method extending ValueEventListener class overriding onDataChange() method.

The documentation reads:

Asynchronous listeners: Data stored in a Firebase Realtime Database is retrieved by attaching an asynchronous listener to a database reference. The listener is triggered once for the initial state of the data and again anytime the data changes. An event listener may receive several different types of events. This mode of data retrieval is supported in Java, Node.js and Python Admin SDKs.

The code generally does what I want, however my callback method is called very late - three, five, seven minutes after the cloud function terminates, as shown by the following log snippet.

DEBUG 2023-01-22T16:01:36.992937150Z [resource.labels.functionName: xxx] [labels.executionId: hijz4xa4t89k] Function execution started

<...>

INFO 2023-01-22T 16:01:45.251247Z [resource.labels.functionName: tht-mailer-function] [labels.executionId: hijz4xa4t89k] ***4. Listener assigned.

DEBUG 2023-01-22T16:01:45.350950544Z [resource.labels.functionName: xxx] [labels.executionId: hijz4xa4t89k] Function execution took 8358 ms, finished with status code: 200

INFO 2023-01-22T 16:07:03.848739Z [resource.labels.functionName: xxx] [labels.executionId: hijz4xa4t89k] ***Inside onDataChange!!!, dataSnapshot = DataSnapshot { key = 

<...>
  

In this specific run it took about 6 minutes (between "***4. Listener assigned" and "***Inside onDataChange!!!" log lines)

Since the documentation states that the callback will be invoked once for the initial state of the data, I expect it to be called immediately, during execution of the Cloud Functions main thread or perhaps a few seconds after its termination. Would you know how to interpret this very long delay and how to avoid it?

Doug Stevenson
  • 297,357
  • 32
  • 422
  • 441
X.Mitry
  • 15
  • 4

1 Answers1

0

Since the documentation states that the callback will be invoked once for the initial state of the data, I expect it to be called immediately

This is not a valid assumption. Database listeners are asynchronous and never return immediately. When you add a listener, that method call returns immediately and the function continues to run before the listener is invoked. You will need to instead make sure you have the data you need and act on it before you allow the Cloud Function to return. When the function returns, it effectively stops (or drastically delays) the async work, as you have observed.

Doug Stevenson
  • 297,357
  • 32
  • 422
  • 441
  • "You will need to instead make sure you have the data you need and act on it before you allow the Cloud Function to return." - You see, the whole purpose of the callback is to get that data. Are you saying that putting the main thread on sleep until the callback returns might help? – X.Mitry Jan 22 '23 at 18:24
  • That's one thing to try. https://stackoverflow.com/a/31702957 – Doug Stevenson Jan 22 '23 at 18:55
  • Putting the main thread to sleep did help! Thanks This is rather peculiar behavior of Cloud Functions. Is it documented anywhere in the GCP docs? Interestingly, when I did not know about this behaviour (When the function returns, it effectively stops or drastically delays the async work) my first instinct was to do the same - put the main thread to sleep, but for a totally different reason - I was thinking that by the time my callback is invoked my class would go out of scope and the callback would simply crash. Obviously this is not the case, but the reality is more interesting... – X.Mitry Jan 23 '23 at 18:40
  • It's the same with JavaScript except you can return a promise that resolves when the work is complete. Java does not really have a natural way of expressing async work. I don't know about docs. – Doug Stevenson Jan 23 '23 at 19:03