FetchConfigs synchronously without callback to support MS Extensions.Configuration

TL;DR

It would be great if there was a RemoteConfigService.FetchConfigs overload that synchronously returned a RuntimeConfig object, rather than relying on a callback.

Use Case

I am trying to implement a RemoteConfig configuration provider for the Microsoft.Extensions.Configuration library (installed as a UPM package via UnityNuGet). See the code on GitHub. The MS Configuration library is pretty powerful, and fairly standard in other .NET applications, so it would be great to use RemoteConfig as a configuration source alongside other sources like JSON files, environment variables, command line options, etc.

Unfortunately, there are some unavoidable issues with a RemoteConfig configuration provider:

  • It cannot load settings by Waiting the Task returned by RemoteConfigService.FetchConfigsAsync, as this would lead to a deadlock with the Unity main thread
  • It cannot load settings in a FetchCompleted listener callback after calling RemoteConfigService.FetchConfigs, as this callback runs at an indeterminate time. The RemoteConfigConfigurationSource constructor could accept a callback and add that as a listener to FetchCompleted, but that breaks the encapsulation/contract of MS configuration sources. Consumers could also wait for a short time after after building configuration to ensure that FetchCompleted has been invoked, but the amount of time would be arbitrary–either too short or longer than necessary.

As such, a RemoteConfig configuration provider can’t really be implemented until either:

  • The Microsoft Configuration system supports building configuration asynchronously (so we could just await FetchConfigsAsync), or
  • Unity RemoteConfig supports synchronous fetching (without a callback)

Hi @Rabadash8820 , thanks for this interesting feature request!

At this point, we can’t really do the web request synchronously without a callback without risking deadlocks.
It also seems that the lack of async support for Configuration Provider was acknowledged but is unlikely to get support anytime soon according to this thread.

The one thing which could work for your use case is if the configuration provider returns the cached version of the config synchronously.
The cached version is available immediately and synchronously, and cca 99% of the time it will be the same as the fetched version.
In simple terms, RemoteConfigService.Instance.appConfig.config
will get the values from the cache upon initialization,
and if the request is successful, both appConfig and cache will be overwritten accordingly.

If there is a change on the backend, it will be cached correctly upon the fetch and can be accessed at the beginning of the next session in the worst-case scenario.

Please let us know if this helps, even though is just a workaround suggestion.

Hi @vd_unity , thanks for the quick reply! That’s interesting, I didn’t know RemoteConfigService.appConfig worked that way. This raises a couple other questions:

  • Which environments are cached? Is it only the default environment, or all of them?
  • If the cached configuration is not loaded in time, will RemoteConfigService.appConfig.GetKeys() return an empty array or null?
  • When does this caching actually take place? Is it during the first accessing of RemoteConfigService.Instance or when the RemoteConfig assembly loads? Does that loading block the Unity thread or is it on a background thread?
  • What is the purpose of ever calling FetchConfigs(Async) then? Is it just for resyncing configuration later, e.g. during a long play session?

Side note: I think some of this info could be more clearly stated in the docs. Happy to help with this if the docs are open source.

Hey @vd_unity, just wanted to be sure you saw my reply here. Based on your answers on my other thread , I think I can answer #1: the environment cached would be the one passed in InitializationOptions.SetEnvironmentName to UnityServices.InitializeAsync, or the default environment if none was passed. Is that correct?

I could still use some insight on the other questions above though. Thanks in advance!