Firebase remote config hair pulling

1,191 views
Skip to first unread message

GKA

unread,
Nov 2, 2016, 7:56:35 PM11/2/16
to Firebase Google Group
Hi,

I need serious help here.

I downloaded the sample Firebase app for Android.

created a new "app" in my console for "com.google.samples.quickstart.config"

Got the google-services.json in the right place and built the app.

I did one change

Instead of 

FirebaseRemoteConfigSettings configSettings = new FirebaseRemoteConfigSettings.Builder()
                .setDeveloperModeEnabled(true)
                .build();

I did
FirebaseRemoteConfigSettings configSettings = new FirebaseRemoteConfigSettings.Builder()
                .setDeveloperModeEnabled(false)
                .build();

So NO DEV MODE.

My param had a default value of "false"
The server had a value of "true".

On 1st run the fetch() was ok and

mFirebaseRemoteConfig.activateFetched()

returned true.

The subsequent 
mFirebaseRemoteConfig.getString() returned also "true" as I expected.

I then changed the value in the console to "false" (same as the local default)

Hitting the "FETCH REMOTE WELCOME" button that does a fetch() and a getString() was still bringing back "true"!!!
I was expecting that if I do fetch() I get the latest value from the server.
I even rebooted the phone but the value I get is still "true".

If I enable dev mode then I get the expected behaviour.

The only explanation I can give is that the value is cached for upto the expiration defined in the fetch.
But this makes absolutely no sense as the value is clearly stale and I am asking for a fetch() which to me 
indicates that I want a fresh value instead of a cached value.

Any ideas of what is going on?
What amI missing?

Thanks in advance.

Todd Kerpelman

unread,
Nov 3, 2016, 12:21:04 PM11/3/16
to Firebase Google Group
It sounds like this is working as intended -- a fetch() call really does mean, "Make a network call, unless you notice that I already have a cached data set that's less than 43,200 seconds (12 hours) old". 

You can override this by calling fetch(long cacheExpirationSeconds), where you can override the normal 43,200 cache value with something smaller. 

Do keep in mind that if you make this very small, you might run up against the client side throttle or the server-side throttle. You can disable (or at least weaken) the client-side throttle by enabling developer mode in your app, but you can't disable the server-side throttle, so make sure that once you're done developing and testing, you increase this cache time back up to something much closer to the default before you release your app to the world.

--T

GKA

unread,
Nov 3, 2016, 2:40:53 PM11/3/16
to Firebase Google Group
Hi Todd, thanks for replying.

I was actually about to reply myself.
I debugged the obfuscated calls and looked at the logic.

You are right, it works as coded but not as described in the docs.

The problem is that this whole workflow - for me - is a mess!

The docs say that fetch(xxxx) gets fresh values.


That is not true.
Not even when I start the app, not even when I reboot the phone!

If fetch() does not guarantee me fresh values then what is the point in calling it myself?

This should be changed to a config setting that I can set once and know that after some time I am guaranteed fresh values by the FirebaseRemoteConfig object.
The FirebaseRemoteConfig handles the schedule and the fetch because ideally I should not care about the fetching and the schedule itself, 
and in reality the fetch() is not guaranteed to do anything!

Why should I be burdened to call fetch() if I am going to be throttled and returned stale cached values instead?

Then, where in the docs is the throttling behaviour described?
What is the minimum cache expiration? (it seems that making it too small makes fetch() fail).
How many fetch() calls am I allowed before I get throttled? 
Are the number of allowed calls to fetch affected by my expiration period?
When is my throttling going to end?

These are important details to make a real-life app that are missing and should be stressed since they pose so many restrictions on usage.

The sample app/code in the docs is way too simple and inadequate.
Fetching on create... If I rotate it will fetch again.
Of course it works because dev=true.
If you switch it off then all bets are off.
It will all depend on how I implemented the fetch() calling process and if I fall into the throttling pit.
Will the user trigger too many fetches?
I need to thing about that!

For me if fetch() returns success then I see no reason for activateFetched() to return false and not apply the values.
if fetch() is throttled or not allowed it should fail with the reason and not return success.

Also all over the docs it is portrayed that all you need to do is cal getXXXX() to get the latest value.
It is not true.
You also need to call fetch() (for freshness but that is not guaranteed)

As a developer since I'll prefer the latest value I will probably bundle fetch() with getXXX() - same as the sample.
But then this will work only every hour!
In an Android App's lifetime an hour is eternity - if you have a long running service then it might still be alive...
I can probably start/stop an app in an hour 10s of times.
They will all get stale values.

So the workflow is:
*) call fetch on startup or every hour in a schedule - or go crazy call freely and be throttled/regulated - end result is the same!
*) if the config changes server side, the app will get the new values after about the 1hr mark (max) - according to the sample's timeout period.

For me the intro videos for Firebase config are a bit misleading.
I got the impression it is more dynamic than it really is - I guess that is my bad.

But docs need a lot more info for fetching/caching/throttling.
And since there is a requirement to throttle/regulate calls to the back-end (to not kill google's servers), fetch should be done for us by specifying the expiration as a config thing.
Or at least make it an option to have the fetch done for us.
This way at least I only need to call getXXXX().

Anyway, lesson is learnt...

Sorry about the rant... 
It is not by any means directed towards you and thanks again for taking the time to reply

Kato Richardson

unread,
Nov 3, 2016, 3:50:12 PM11/3/16
to Firebase Google Group
Hi "GKA",

Great feedback. Thanks for the detail! Will make sure this is passed on to some of the people working on the next set of improvements for RC. They'll be excited to hear some of this.

It may help to understand the use case here, and why a delay in updates affects you outside of debugging and testing. I'm guessing we've run into a bit of an XY problem, as in, you're trying to solve a particular use case (which may have better answers) and that we're instead discussing the proposed solution--that RC needs to cache things differently.

To give an example of why this may matter: Depending on the use case you're trying to resolve, maybe the Realtime Database would be a better answer, since updates are always pushed in milliseconds. 

Excited to hear more about the underlying problem here.

☼, Kato



--
You received this message because you are subscribed to the Google Groups "Firebase Google Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to firebase-talk+unsubscribe@googlegroups.com.
To post to this group, send email to fireba...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/firebase-talk/edeee38d-b3af-4792-94ee-d03666f7bd88%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.



--

Kato Richardson | Developer Programs Eng | kato...@google.com | 775-235-8398

Kato Richardson

unread,
Nov 3, 2016, 5:47:50 PM11/3/16
to Firebase Google Group
One quick addition here, while raising this feedback (thanks again!) I was linked over to this FAQ section, which does seem to address some of the problem. We'll figure out how to get this info cross-referenced and a little more visible, as well as some adding clarification to the Policies and Limits section, and also to the API Overview.

Cheers,
Kato

GKA

unread,
Nov 3, 2016, 6:59:41 PM11/3/16
to Firebase Google Group
Hi Kato,

Thank you for your comments and the DB suggestion.

My rant/thinking was in terms of general usability of the SDK/library.
If I was the developer of Firebase RC, the scenarios I described would be what I would run through and see if they make sense.

The problem I am trying to solve is as simple as the one the sample tries to solve.
Enabling a feature or changing the message or as the RC promo video shows change theme for the app.
To answer your question about why a delay would cause problems other than in a debug scenario I'd refer you to the promo video and the 9M Swedish people being mad at me for bad language.
Admittedly RC provides a better solution even if it is delayed compared to a release cycle.
But it is not stressed enough in the docs that *there is a delay*.

So here is where I got "lost": 
RC promises me dynamic config.
I see a fetch(xxx) call that lets me specify an expiration (should be called cache lifetime duration or something). 
The doc tells me I can get fresh data with it.
Of course as a dev I will be greedy!
I'd want the value as soon as it is published!
I'll minimise the expiration.

Multiply me by millions. Your servers are fried!
So you have to enforce some policy to keep a balance.

I totally understand.

Unfortunately the docs were not as detailed and exact as I'd expect and a few things threw me off.
For example the way fetch(xxx) behaves is not really consistent, it tells me success but doesn't fetch anything.
(Actually I don't know if it fetched something or not, I looked at the code and it seems that activateFetched() checks the timestamps and returns false if it doesn't like it)
I'd expect to get a failure and the reason: throttled, not expired, no network, etc.

And then the whole minimum silently enforced cache duration (not expiration) just makes the fetch(xxx) a burden.
Again as a dev (apart from greedy) I am also lazy.
I'd want to do just one call: getXXXX()
That gets me the latest.
If that is the latest from the server cool. If not ok.
But of course if I have to choose I'd always pick latest.
Which means I will do fetch() + getXXX().
That means I will definitely get into trouble with the throttling police.

So since, there is moratorium, why doesn't the RC handle the fetching completely?
It knows the throttling rules better than every dev out there.
So an option to have RC auto-run a fetch every cache duration seems a good solution.
As it is now I can fine tune the fetch()/getXXX() but really I don't see how me running the fetch() will give me a benefit because of the imposed moratorium.
Also keep in mind I am not interested in the fetch, I am interested in the getXXX() and the freshness.

So I think these are pretty standard things a dev will consider for RC.

TBH I looked at the DB that you suggested before going to RC but for the DB I saw I needed authentication and I didn't want to go down that road.
Maybe I just didn't delve into it enough to see how I can achieve generic DB access for all users without auth.
I'll take another look for sure.

And just another crazy idea just popped in my head:
Why isn't RC a specialised/restricted to one "table" and app level auth Realtime DB case?
(Again stressing I don't know enough about the DB...)


Thanks again for bearing my ranting...
G
To unsubscribe from this group and stop receiving emails from it, send an email to firebase-tal...@googlegroups.com.

To post to this group, send email to fireba...@googlegroups.com.

Kato Richardson

unread,
Nov 3, 2016, 7:35:36 PM11/3/16
to Firebase Google Group
Again, great feedback here. Thanks so much for spending the time to share it. It's a lot to think about and I will ensure that it's discussed!

☼, Kato

To unsubscribe from this group and stop receiving emails from it, send an email to firebase-talk+unsubscribe@googlegroups.com.

To post to this group, send email to fireba...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

GKA

unread,
Nov 3, 2016, 7:58:43 PM11/3/16
to Firebase Google Group
Hi Kato,

thanks for this.

Exactly what I was missing!!!

TBH this belongs in the Docs so yes it'd be great if you added it there as well.

But it needs more clarification as to minimum expiration etc.

G
To unsubscribe from this group and stop receiving emails from it, send an email to firebase-tal...@googlegroups.com.

To post to this group, send email to fireba...@googlegroups.com.
--

Kato Richardson | Developer Programs Eng | kato...@google.com | 775-235-8398

Reply all
Reply to author
Forward
0 new messages