Skip to content

Commit

Permalink
Fix cache key
Browse files Browse the repository at this point in the history
  • Loading branch information
marcospassos committed Sep 6, 2024
1 parent 005fc8d commit 6e27a04
Show file tree
Hide file tree
Showing 6 changed files with 61 additions and 7 deletions.
22 changes: 22 additions & 0 deletions src/hash.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import {hash} from './hash';

describe('hash', () => {
it('should generate a hash from a string', () => {
const result = hash('foo');

expect(result).toEqual('18cc6');
expect(result).toEqual(hash('foo'));
});

it('should handle special characters', () => {
expect(hash('✨')).toEqual('2728');
expect(hash('💥')).toEqual('d83d');
expect(hash('✨💥')).toEqual('59615');
});

it('should generate a hash from an empty string', () => {
const result = hash('');

expect(result).toEqual('0');
});
});
12 changes: 12 additions & 0 deletions src/hash.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export function hash(value: string): string {
let code = 0;

for (const char of value) {
const charCode = char.charCodeAt(0);

code = (code << 5) - code + charCode;
code |= 0; // Convert to 32bit integer
}

return code.toString(16);
}
12 changes: 9 additions & 3 deletions src/hooks/useContent.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {Plug} from '@croct/plug';
import {useCroct} from './useCroct';
import {useLoader} from './useLoader';
import {useContent} from './useContent';
import {hash} from '../hash';

jest.mock(
'./useCroct',
Expand Down Expand Up @@ -30,11 +31,15 @@ describe('useContent (CSR)', () => {
jest.mocked(useLoader).mockReturnValue('foo');

const slotId = 'home-banner@1';
const preferredLocale = 'en';
const attributes = {example: 'value'};
const cacheKey = 'unique';

const {result} = renderHook(
() => useContent<{title: string}>(slotId, {
preferredLocale: 'en',
cacheKey: 'unique',
preferredLocale: preferredLocale,
attributes: attributes,
cacheKey: cacheKey,
fallback: {
title: 'error',
},
Expand All @@ -44,7 +49,7 @@ describe('useContent (CSR)', () => {

expect(useCroct).toHaveBeenCalled();
expect(useLoader).toHaveBeenCalledWith({
cacheKey: `useContent:unique:${slotId}`,
cacheKey: hash(`useContent:${cacheKey}:${slotId}:${preferredLocale}:${JSON.stringify(attributes)}`),
fallback: {
title: 'error',
},
Expand All @@ -59,6 +64,7 @@ describe('useContent (CSR)', () => {

expect(fetch).toHaveBeenCalledWith(slotId, {
preferredLocale: 'en',
attributes: attributes,
});

expect(result.current).toBe('foo');
Expand Down
9 changes: 8 additions & 1 deletion src/hooks/useContent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {FetchOptions} from '@croct/plug/plug';
import {useLoader} from './useLoader';
import {useCroct} from './useCroct';
import {isSsr} from '../ssr-polyfills';
import {hash} from '../hash';

export type UseContentOptions<I, F> = FetchOptions & {
fallback?: F,
Expand All @@ -17,10 +18,16 @@ function useCsrContent<I, F>(
options: UseContentOptions<I, F> = {},
): SlotContent | I | F {
const {fallback, initial, cacheKey, expiration, ...fetchOptions} = options;
const {preferredLocale} = fetchOptions;
const croct = useCroct();

return useLoader({
cacheKey: `useContent:${cacheKey ?? ''}:${id}`,
cacheKey: hash(
`useContent:${cacheKey ?? ''}`
+ `:${id}`
+ `:${preferredLocale ?? ''}`
+ `:${JSON.stringify(fetchOptions.attributes ?? '')}`,
),
loader: () => croct.fetch(id, fetchOptions).then(({content}) => content),
initial: initial,
fallback: fallback,
Expand Down
6 changes: 4 additions & 2 deletions src/hooks/useEvaluation.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {Plug} from '@croct/plug';
import {useEvaluation} from './useEvaluation';
import {useCroct} from './useCroct';
import {useLoader} from './useLoader';
import {hash} from '../hash';

jest.mock(
'./useCroct',
Expand Down Expand Up @@ -39,19 +40,20 @@ describe('useEvaluation', () => {
jest.mocked(useLoader).mockReturnValue('foo');

const query = 'location';
const cacheKey = 'unique';

const {result} = renderHook(
() => useEvaluation(query, {
...evaluationOptions,
cacheKey: 'unique',
cacheKey: cacheKey,
fallback: 'error',
expiration: 50,
}),
);

expect(useCroct).toHaveBeenCalled();
expect(useLoader).toHaveBeenCalledWith({
cacheKey: 'useEvaluation:unique:location:{"foo":"bar"}',
cacheKey: hash(`useEvaluation:${cacheKey}:${query}:${JSON.stringify(evaluationOptions.attributes)}`),
fallback: 'error',
expiration: 50,
loader: expect.any(Function),
Expand Down
7 changes: 6 additions & 1 deletion src/hooks/useEvaluation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {EvaluationOptions} from '@croct/sdk/facade/evaluatorFacade';
import {useLoader} from './useLoader';
import {useCroct} from './useCroct';
import {isSsr} from '../ssr-polyfills';
import {hash} from '../hash';

function cleanEvaluationOptions(options: EvaluationOptions): EvaluationOptions {
const result: EvaluationOptions = {};
Expand Down Expand Up @@ -36,7 +37,11 @@ function useCsrEvaluation<T = JsonValue, I = T, F = T>(
const croct = useCroct();

return useLoader<T | I | F>({
cacheKey: `useEvaluation:${cacheKey ?? ''}:${query}:${JSON.stringify(options.attributes ?? '')}`,
cacheKey: hash(
`useEvaluation:${cacheKey ?? ''}`
+ `:${query}`
+ `:${JSON.stringify(options.attributes ?? '')}`,
),
loader: () => croct.evaluate<T & JsonValue>(query, cleanEvaluationOptions(evaluationOptions)),
initial: initial,
fallback: fallback,
Expand Down

0 comments on commit 6e27a04

Please sign in to comment.