Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/modules/diet/food/application/usecases/foodCrud.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
importFoodsFromApiByName,
} from '~/modules/diet/food/infrastructure/api/application/apiFood'
import { createSupabaseFoodRepository } from '~/modules/diet/food/infrastructure/api/infrastructure/supabase/supabaseFoodRepository'
import { isSearchCached } from '~/modules/search/application/usecases/cachedSearchCrud'
import { searchUseCases } from '~/modules/search/application/usecases/searchUseCases'
import { showPromise } from '~/modules/toast/application/toastManager'
import { setBackendOutage } from '~/shared/error/backendOutageSignal'
import { formatError } from '~/shared/formatError'
Expand Down Expand Up @@ -42,7 +42,7 @@ export async function fetchFoodsByName(
params: FoodSearchParams = {},
): Promise<readonly Food[]> {
try {
const isCached = await isSearchCached(name)
const isCached = await searchUseCases.isSearchCached(name)

if (!isCached) {
await showPromise(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import axios from 'axios'
import { type Food } from '~/modules/diet/food/domain/food'
import { type ApiFood } from '~/modules/diet/food/infrastructure/api/domain/apiFoodSchema'
import { createSupabaseFoodRepository } from '~/modules/diet/food/infrastructure/api/infrastructure/supabase/supabaseFoodRepository'
import { markSearchAsCached } from '~/modules/search/application/usecases/cachedSearchCrud'
import { searchUseCases } from '~/modules/search/application/usecases/searchUseCases'
import { showError } from '~/modules/toast/application/toastManager'
import { convertApi2Food } from '~/shared/utils/convertApi2Food'
import { ORIGINAL_ERROR_SYMBOL } from '~/shared/utils/errorUtils'
Expand Down Expand Up @@ -99,11 +99,11 @@ export async function importFoodsFromApiByName(name: string): Promise<Food[]> {
)
} else {
logging.debug('No RELEVANT failed upsertions, marking search as cached')
await markSearchAsCached(name)
await searchUseCases.markSearchAsCached(name)
}
} else {
logging.debug('No failed upsertions, marking search as cached')
await markSearchAsCached(name)
await searchUseCases.markSearchAsCached(name)
}

const upsertedFoods: ReadonlyArray<Food | null> = upsertionResults
Expand Down
Empty file.
52 changes: 52 additions & 0 deletions src/modules/search/application/store/cachedSearchCacheStore.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { createSignal } from 'solid-js'

import { type CachedSearch } from '~/modules/search/domain/cachedSearch'
import { logging } from '~/shared/utils/logging'

export function createCachedSearchCacheStore() {
const [cachedSearches, setCachedSearches] = createSignal<
readonly CachedSearch[]
>([])

return {
// Upsert to cache (from realtime events)
upsertToCache: (cachedSearch: CachedSearch) => {
const current = cachedSearches()
const existingIndex = current.findIndex(
(search) => search.search === cachedSearch.search,
)

if (existingIndex >= 0) {
// Update existing
const updated = [...current]
updated[existingIndex] = cachedSearch
setCachedSearches(updated)
logging.debug('Updated cached search in cache:', { cachedSearch })
} else {
// Add new
setCachedSearches([cachedSearch, ...current])
logging.debug('Added new cached search to cache:', { cachedSearch })
}
},

// Remove from cache (from realtime events)
removeFromCache: (selector: {
by: 'search'
value: CachedSearch['search']
}) => {
const current = cachedSearches()
const searchToRemove = current.find(
(search) => search.search === selector.value,
)

if (searchToRemove) {
const updated = current.filter(
(search) => search.search !== selector.value,
)
setCachedSearches(updated)

logging.debug('Removed cached search from cache:', { searchToRemove })
}
},
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import {
fetchUserRecipes,
} from '~/modules/diet/recipe/application/usecases/recipeCrud'
import { fetchUserRecentFoods } from '~/modules/recent-food/application/usecases/recentFoodCrud'
import { fetchTemplatesByTabLogic } from '~/modules/template-search/application/templateSearchLogic'
import { fetchTemplatesByTabLogic } from '~/modules/search/application/usecases/templateSearchLogic'
import { type TemplateSearchTab } from '~/modules/search/ui/TemplateSearchTabs'
import { currentUser, currentUserId } from '~/modules/user/application/user'
import { type TemplateSearchTab } from '~/sections/search/components/TemplateSearchTabs'
import { createDebouncedSignal } from '~/shared/utils/createDebouncedSignal'

export const [templateSearch, setTemplateSearch] = createSignal<string>('')
Expand Down
26 changes: 15 additions & 11 deletions src/modules/search/application/usecases/cachedSearchCrud.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
import { createCachedSearchRepository } from '~/modules/search/infrastructure/cachedSearchRepository'
import { type CachedSearchRepository } from '~/modules/search/domain/searchRepository'

const cachedSearchRepository = createCachedSearchRepository()
export function createCachedSearchCrudUseCases(
cachedSearchRepository: CachedSearchRepository,
) {
return {
async isSearchCached(query: string): Promise<boolean> {
return await cachedSearchRepository.isSearchCached(query)
},

export async function isSearchCached(query: string): Promise<boolean> {
return await cachedSearchRepository.isSearchCached(query)
}

export async function markSearchAsCached(query: string): Promise<void> {
await cachedSearchRepository.markSearchAsCached(query)
}
async markSearchAsCached(query: string): Promise<void> {
await cachedSearchRepository.markSearchAsCached(query)
},

export async function unmarkSearchAsCached(query: string): Promise<void> {
await cachedSearchRepository.unmarkSearchAsCached(query)
async unmarkSearchAsCached(query: string): Promise<void> {
await cachedSearchRepository.unmarkSearchAsCached(query)
},
}
}
65 changes: 65 additions & 0 deletions src/modules/search/application/usecases/searchUseCases.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { createRoot } from 'solid-js'

import { createCachedSearchCacheStore } from '~/modules/search/application/store/cachedSearchCacheStore'
import { createCachedSearchCrudUseCases } from '~/modules/search/application/usecases/cachedSearchCrud'
import { cachedSearchSchema } from '~/modules/search/domain/cachedSearch'
import { createCachedSearchRepository } from '~/modules/search/infrastructure/cachedSearchRepository'
import { initializeCachedSearchRealtime } from '~/modules/search/infrastructure/supabase/realtime'
import { parseWithStack } from '~/shared/utils/parseWithStack'

const { cachedSearchCacheStore, cachedSearchCrudUseCases } = createRoot(() => {
const cachedSearchCacheStore = createCachedSearchCacheStore()
const cachedSearchRepository = createCachedSearchRepository()
const cachedSearchCrudUseCases = createCachedSearchCrudUseCases(
cachedSearchRepository,
)

initializeCachedSearchRealtime({
onInsert: (newRecord) => {
cachedSearchCacheStore.upsertToCache(newRecord)
},
onUpdate: (newRecord) => {
cachedSearchCacheStore.upsertToCache(newRecord)
},
onDelete: (oldRecord) => {
cachedSearchCacheStore.removeFromCache({
by: 'search',
value: oldRecord.search,
})
},
})

return { cachedSearchCacheStore, cachedSearchCrudUseCases }
})

export const searchUseCases = {
isSearchCached: async (query: string): Promise<boolean> => {
const result = await cachedSearchCrudUseCases.isSearchCached(query)
if (result) {
cachedSearchCacheStore.upsertToCache(
parseWithStack(cachedSearchSchema, { search: query }),
)
} else {
cachedSearchCacheStore.removeFromCache({
by: 'search',
value: query,
})
}
return result
},
markSearchAsCached: async (query: string): Promise<void> => {
await cachedSearchCrudUseCases.markSearchAsCached(query)
cachedSearchCacheStore.upsertToCache(
parseWithStack(cachedSearchSchema, {
search: query,
}),
)
},
unmarkSearchAsCached: async (query: string): Promise<void> => {
await cachedSearchCrudUseCases.unmarkSearchAsCached(query)
cachedSearchCacheStore.removeFromCache({
by: 'search',
value: query,
})
},
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import type { Food } from '~/modules/diet/food/domain/food'
import type { FoodSearchParams } from '~/modules/diet/food/domain/foodRepository'
import type { Recipe } from '~/modules/diet/recipe/domain/recipe'
import type { Template } from '~/modules/diet/template/domain/template'
import { availableTabs } from '~/modules/search/ui/TemplateSearchTabs'
import { type User } from '~/modules/user/domain/user'
import { availableTabs } from '~/sections/search/components/TemplateSearchTabs'

/**
* Dependencies for fetchTemplatesByTabLogic
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ import {
import {
fetchTemplatesByTabLogic,
type FetchTemplatesDeps,
} from '~/modules/template-search/application/templateSearchLogic'
import { availableTabs } from '~/sections/search/components/TemplateSearchTabs'
} from '~/modules/search/application/usecases/templateSearchLogic'
import { availableTabs } from '~/modules/search/ui/TemplateSearchTabs'

describe('fetchTemplatesByTabLogic', () => {
const mockFood = promoteNewFoodToFood(
Expand Down
38 changes: 6 additions & 32 deletions src/modules/search/infrastructure/cachedSearchRepository.ts
Original file line number Diff line number Diff line change
@@ -1,41 +1,15 @@
import { cachedSearchSchema } from '~/modules/search/domain/cachedSearch'
import { type CachedSearchRepository } from '~/modules/search/domain/searchRepository'
import { cachedSearchCacheStore } from '~/modules/search/infrastructure/signals/cachedSearchCacheStore'
import { createSupabaseCachedSearchGateway } from '~/modules/search/infrastructure/supabase/supabaseCachedSearchGateway'
import { parseWithStack } from '~/shared/utils/parseWithStack'

export function createCachedSearchRepository(): CachedSearchRepository {
const gateway = createSupabaseCachedSearchGateway()

return {
isSearchCached: async (searchQuery) => {
const result = await gateway.isSearchCached(searchQuery)
if (result) {
cachedSearchCacheStore.upsertToCache(
parseWithStack(cachedSearchSchema, { search: searchQuery }),
)
} else {
cachedSearchCacheStore.removeFromCache({
by: 'search',
value: searchQuery,
})
}
return result
},
markSearchAsCached: async (searchQuery) => {
await gateway.markSearchAsCached(searchQuery)
cachedSearchCacheStore.upsertToCache(
parseWithStack(cachedSearchSchema, {
search: searchQuery,
}),
)
},
unmarkSearchAsCached: async (searchQuery) => {
await gateway.unmarkSearchAsCached(searchQuery)
cachedSearchCacheStore.removeFromCache({
by: 'search',
value: searchQuery,
})
},
isSearchCached: async (searchQuery) =>
await gateway.isSearchCached(searchQuery),
markSearchAsCached: async (searchQuery) =>
await gateway.markSearchAsCached(searchQuery),
unmarkSearchAsCached: async (searchQuery) =>
await gateway.unmarkSearchAsCached(searchQuery),
}
}

This file was deleted.

24 changes: 0 additions & 24 deletions src/modules/search/infrastructure/signals/cachedSearchEffects.ts

This file was deleted.

Loading