CesiumGS / cesium-native

Apache License 2.0
438 stars 215 forks source link

What's the correct way of enabling caching for requests? #989

Closed LukasPoque closed 1 week ago

LukasPoque commented 2 weeks ago

We're currently in the process of building a Flutter package that enables everybody to use 3D Tiles in their Flutter projects: https://github.com/odd-io/cesium_3d_native Currently, we use a wrapper around Filament to enable rendering on (all) supported platforms named Thermion. When Impeller and FlutterGPU are coming to all platforms we are prepared to switch to this rendering layer. The basic setup is working already and it is possible to see even multiple tilesets.

The problem we're encountering now is that the loading of the parts that are out of view for some time is not as fast as wished. Especially when switching between complete tilesets (for example to show different tilesets at the same location for displaying time-based changes between them) it takes some time until the new tileset is loaded again. I think if it's possible to cache these requests it would enable a smoother experience.

I looked into the CesiumAsync Library and found CachingAssetAccessor and the ICacheDatabase / SqliteCache classes. My question is how exactly are they supposed to be used?

This is how I thought it was supposed to be but sadly no responses are being saved (and the storeEntry method is never called):

pAssetAccessor = std::make_shared<IAssetAccessor>();

std::string cacheDbPath = "cesium_tile_cache.db";
pCacheDatabase = std::make_shared<CesiumAsync::SqliteCache>(
    spdlog::default_logger(),
    cacheDbPath,
    4096
);

pAssetAccessor = std::make_shared<CesiumAsync::CachingAssetAccessor>(
        spdlog::default_logger(),
        pAssetAccessor,
        pCacheDatabase,
        10000
    );

// Using this AssesAccessor in TilesetExternals when creating a new tileset

Do I need to do something else to enable caching?

Happy for any ideas/help 🙂

LukasPoque commented 2 weeks ago

I noticed I made a mistake in the example code because I removed a custom IAssetAccessor implementation that our package was using and I was not aware that the IAssetAccessor class is only an abstract interface and can not be directly used. But my question is still valid. So let's say I'm implementing an AssetAccessor based on curl, do I need to do something special to support caching or is this handled directly from the CachingAssetAccessor decorator?

kring commented 1 week ago

Hi @LukasPoque, that sounds like a really cool project!

Your example code looks roughly correct to me. For comparison, here's where we set up the caching in Cesium for Unreal and Cesium for Unity:

https://github.com/CesiumGS/cesium-unreal/blob/v2.10.0/Source/CesiumRuntime/Private/CesiumRuntime.cpp#L119 https://github.com/CesiumGS/cesium-unity/blob/v1.13.1/native~/Editor/src/UnityExternals.cpp#L41

If you think you have this right, but caching is still not working, the next thing I'd check is your HTTP headers. CachingAssetAccessor attempts to honor HTTP caching-related headers. So if your asset accessor isn't passing through request/response headers, or if it is but those headers forbid caching, then the responses will not be cached.

LukasPoque commented 1 week ago

@kring, thanks. We really hope to bring this package into a minimal but stable version. Right now, there is no way to add 3D maps (or even 2.5D maps) to a Flutter app without having a different implementation (or at least a package that creates these) for the different platforms. The biggest map package, flutter_map, also does not support these things.

Regarding the not working cache, I think your suggestion was spot on. I looked into our AssetAccessor implementation and we just ignored the headers. It's working now 🎉