From 75f4b9713585213d93f70932c9fcb2378170066a Mon Sep 17 00:00:00 2001 From: Mitchell McCaffrey Date: Mon, 22 Mar 2021 21:23:43 +1100 Subject: [PATCH] Moved asset manifest to use partial network updates and fix asset cache ignoring changes --- src/components/token/Tokens.js | 6 ++- src/contexts/TokenDataContext.js | 4 +- src/network/NetworkedMapAndTokens.js | 59 ++++++++++------------------ 3 files changed, 28 insertions(+), 41 deletions(-) diff --git a/src/components/token/Tokens.js b/src/components/token/Tokens.js index c107ee7..c56feec 100644 --- a/src/components/token/Tokens.js +++ b/src/components/token/Tokens.js @@ -41,7 +41,11 @@ function Tokens({ onMapTokenStateCreate }) { visible: true, }); // Update last used for cache invalidation - updateToken(token.id, { lastUsed: Date.now() }); + // Keep last modified the same + updateToken(token.id, { + lastUsed: Date.now(), + lastModified: token.lastModified, + }); } } diff --git a/src/contexts/TokenDataContext.js b/src/contexts/TokenDataContext.js index d705705..329a509 100644 --- a/src/contexts/TokenDataContext.js +++ b/src/contexts/TokenDataContext.js @@ -130,7 +130,7 @@ export function TokenDataProvider({ children }) { const updateToken = useCallback( async (id, update) => { - const change = { ...update, lastModified: Date.now() }; + const change = { lastModified: Date.now(), ...update }; await database.table("tokens").update(id, change); }, [database] @@ -138,7 +138,7 @@ export function TokenDataProvider({ children }) { const updateTokens = useCallback( async (ids, update) => { - const change = { ...update, lastModified: Date.now() }; + const change = { lastModified: Date.now(), ...update }; await Promise.all( ids.map((id) => database.table("tokens").update(id, change)) ); diff --git a/src/network/NetworkedMapAndTokens.js b/src/network/NetworkedMapAndTokens.js index 601fbe8..435471e 100644 --- a/src/network/NetworkedMapAndTokens.js +++ b/src/network/NetworkedMapAndTokens.js @@ -44,7 +44,7 @@ function NetworkedMapAndTokens({ session }) { isLoading, } = useMapLoading(); - const { putToken, updateToken, getTokenFromDB } = useTokenData(); + const { putToken, getTokenFromDB } = useTokenData(); const { putMap, updateMap, getMapFromDB, updateMapState } = useMapData(); const [currentMap, setCurrentMap] = useState(null); @@ -61,14 +61,15 @@ function NetworkedMapAndTokens({ session }) { session, "manifest", 500, - false + true, + "mapId" ); async function loadAssetManifestFromMap(map, mapState) { - const assets = []; + const assets = { mapId: map.id }; if (map.type === "file") { const { id, lastModified, owner } = map; - assets.push({ type: "map", id, lastModified, owner }); + assets[`map-${id}`] = { type: "map", id, lastModified, owner }; } let processedTokens = new Set(); for (let tokenState of Object.values(mapState.tokens)) { @@ -81,10 +82,10 @@ function NetworkedMapAndTokens({ session }) { processedTokens.add(tokenState.tokenId); // Omit file from token peer will request file if needed const { id, lastModified, owner } = token; - assets.push({ type: "token", id, lastModified, owner }); + assets[`token-${id}`] = { type: "token", id, lastModified, owner }; } } - setAssetManifest(assets); + setAssetManifest(assets, true, true); } function compareAssets(a, b) { @@ -95,26 +96,23 @@ function NetworkedMapAndTokens({ session }) { function assetNeedsUpdate(oldAsset, newAsset) { return ( compareAssets(oldAsset, newAsset) && - oldAsset.lastModified > newAsset.lastModified + oldAsset.lastModified < newAsset.lastModified ); } function addAssetIfNeeded(asset) { - // Asset needs updating - const exists = assetManifest?.some((oldAsset) => - compareAssets(oldAsset, asset) - ); - const needsUpdate = assetManifest?.some((oldAsset) => - assetNeedsUpdate(oldAsset, asset) - ); - if (!exists || needsUpdate) { - setAssetManifest((prevAssets) => [ - ...(prevAssets || []).filter( - (prevAsset) => !compareAssets(prevAsset, asset) - ), - asset, - ]); - } + setAssetManifest((prevAssets) => { + const id = asset.type === "map" ? `map-${asset.id}` : `token-${asset.id}`; + const exists = id in prevAssets; + const needsUpdate = exists && assetNeedsUpdate(prevAssets[id], asset); + if (!exists || needsUpdate) { + return { + ...prevAssets, + [id]: asset, + }; + } + return prevAssets; + }); } // Keep track of assets we are already requesting to prevent from loading them multiple times @@ -126,7 +124,7 @@ function NetworkedMapAndTokens({ session }) { } async function requestAssetsIfNeeded() { - for (let asset of assetManifest) { + for (let asset of Object.values(assetManifest)) { if ( asset.owner === userId || requestingAssetsRef.current.has(asset.id) @@ -147,12 +145,7 @@ function NetworkedMapAndTokens({ session }) { const cachedMap = await getMapFromDB(asset.id); if (cachedMap && cachedMap.lastModified === asset.lastModified) { requestingAssetsRef.current.delete(asset.id); - continue; } else if (cachedMap && cachedMap.lastModified > asset.lastModified) { - // Update last used for cache invalidation - const lastUsed = Date.now(); - await updateMap(cachedMap.id, { lastUsed }); - setCurrentMap({ ...cachedMap, lastUsed }); requestingAssetsRef.current.delete(asset.id); } else { session.sendTo(owner.sessionId, "mapRequest", asset.id); @@ -161,15 +154,6 @@ function NetworkedMapAndTokens({ session }) { const cachedToken = await getTokenFromDB(asset.id); if (cachedToken && cachedToken.lastModified === asset.lastModified) { requestingAssetsRef.current.delete(asset.id); - continue; - } else if ( - cachedToken && - cachedToken.lastModified > asset.lastModified - ) { - // Update last used for cache invalidation - const lastUsed = Date.now(); - await updateToken(cachedToken.id, { lastUsed }); - requestingAssetsRef.current.delete(asset.id); } else { session.sendTo(owner.sessionId, "tokenRequest", asset.id); } @@ -185,7 +169,6 @@ function NetworkedMapAndTokens({ session }) { getMapFromDB, getTokenFromDB, updateMap, - updateToken, userId, ]);