Add caching mechanism to API calls
							parent
							
								
									54daa904be
								
							
						
					
					
						commit
						161904f65a
					
				| 
						 | 
					@ -8,6 +8,39 @@ export const useClientStore = defineStore("client", () => {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const calls = new Map<string, Promise<any>>();
 | 
					  const calls = new Map<string, Promise<any>>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  type CachedValue<T> = {
 | 
				
			||||||
 | 
					    value: T,
 | 
				
			||||||
 | 
					    timestamp: number,
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const cached = new Map<string, any>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  function callCached<T>(
 | 
				
			||||||
 | 
					    key: string,
 | 
				
			||||||
 | 
					    apiCall: () => CancelablePromise<T>,
 | 
				
			||||||
 | 
					    maxLifetime: number = 2000,
 | 
				
			||||||
 | 
					    thenOnce?: (result: T) => T,
 | 
				
			||||||
 | 
					    catchOnce?: (error: any) => any,
 | 
				
			||||||
 | 
					    finallyOnce?: () => void,
 | 
				
			||||||
 | 
					  ): Promise<T> {
 | 
				
			||||||
 | 
					    if (cached.has(key)) {
 | 
				
			||||||
 | 
					      const cachedValue = cached.get(key) as CachedValue<T>;
 | 
				
			||||||
 | 
					      if (Date.now() - cachedValue.timestamp < maxLifetime) {
 | 
				
			||||||
 | 
					        return Promise.resolve(cachedValue.value);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // cache miss
 | 
				
			||||||
 | 
					    let promise = call(key, apiCall, thenOnce, catchOnce, finallyOnce);
 | 
				
			||||||
 | 
					    promise.then((result) => {
 | 
				
			||||||
 | 
					      cached.set(key, {
 | 
				
			||||||
 | 
					        value: result,
 | 
				
			||||||
 | 
					        timestamp: Date.now(),
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					    return promise;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  function call<T>(
 | 
					  function call<T>(
 | 
				
			||||||
    key: string,
 | 
					    key: string,
 | 
				
			||||||
    apiCall: () => CancelablePromise<T>,
 | 
					    apiCall: () => CancelablePromise<T>,
 | 
				
			||||||
| 
						 | 
					@ -17,11 +50,15 @@ export const useClientStore = defineStore("client", () => {
 | 
				
			||||||
  ): Promise<T> {
 | 
					  ): Promise<T> {
 | 
				
			||||||
    console.log("Fetching call " + key);
 | 
					    console.log("Fetching call " + key);
 | 
				
			||||||
    if (!calls.has(key)) {
 | 
					    if (!calls.has(key)) {
 | 
				
			||||||
 | 
					      console.log("Making new call " + key);
 | 
				
			||||||
      const promise = apiCall();
 | 
					      const promise = apiCall();
 | 
				
			||||||
      calls.set(key, promise);
 | 
					      calls.set(key, promise);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // remove from calls once completed
 | 
					      // remove from calls once completed
 | 
				
			||||||
      promise.finally(() => calls.delete(key));
 | 
					      promise.finally(() => {
 | 
				
			||||||
 | 
					        console.log("Call " + key + " completed");
 | 
				
			||||||
 | 
					        calls.delete(key);
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // only execute this "then" once if the call was just freshly made
 | 
					      // only execute this "then" once if the call was just freshly made
 | 
				
			||||||
      if (thenOnce) {
 | 
					      if (thenOnce) {
 | 
				
			||||||
| 
						 | 
					@ -37,6 +74,8 @@ export const useClientStore = defineStore("client", () => {
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      return promise;
 | 
					      return promise;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      console.log("Returning concurrent call " + key);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return calls.get(key) as Promise<T>;
 | 
					    return calls.get(key) as Promise<T>;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
| 
						 | 
					@ -44,6 +83,7 @@ export const useClientStore = defineStore("client", () => {
 | 
				
			||||||
  return {
 | 
					  return {
 | 
				
			||||||
    client,
 | 
					    client,
 | 
				
			||||||
    call,
 | 
					    call,
 | 
				
			||||||
 | 
					    callCached,
 | 
				
			||||||
    calls,
 | 
					    calls,
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -33,7 +33,7 @@ export const useTeamsStore = defineStore("teams", () => {
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  async function fetchTeam(id: number) {
 | 
					  async function fetchTeam(id: number) {
 | 
				
			||||||
    const response = await clientStore.call(
 | 
					    const response = await clientStore.callCached(
 | 
				
			||||||
      fetchTeam.name,
 | 
					      fetchTeam.name,
 | 
				
			||||||
      () => client.default.getTeam(id)
 | 
					      () => client.default.getTeam(id)
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
| 
						 | 
					@ -42,7 +42,7 @@ export const useTeamsStore = defineStore("teams", () => {
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  async function fetchTeamMembers(id: number) {
 | 
					  async function fetchTeamMembers(id: number) {
 | 
				
			||||||
    const response = await clientStore.call(
 | 
					    const response = await clientStore.callCached(
 | 
				
			||||||
      fetchTeamMembers.name,
 | 
					      fetchTeamMembers.name,
 | 
				
			||||||
      () => client.default.getTeamMembers(id)
 | 
					      () => client.default.getTeamMembers(id)
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue