Skip to content

Commit

Permalink
Hide cache details from caching http client
Browse files Browse the repository at this point in the history
Refs: #2186
  • Loading branch information
erkannt committed Jan 17, 2025
1 parent 4fa16e3 commit e97d454
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 30 deletions.
31 changes: 5 additions & 26 deletions src/CachingHttpClient.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,4 @@
import {
Headers,
HttpClient,
HttpClientResponse,
UrlParams,
type HttpClientError,
type HttpClientRequest,
} from '@effect/platform'
import { HttpClient, type HttpClientError, type HttpClientRequest, type HttpClientResponse } from '@effect/platform'
import { diff } from 'deep-object-diff'
import { DateTime, Effect, pipe, type Scope } from 'effect'
import * as HttpCache from './HttpCache.js'
Expand All @@ -24,8 +17,7 @@ export const CachingHttpClient: Effect.Effect<
Effect.gen(function* () {
const timestamp = yield* DateTime.now
const req = yield* request
const key = keyForRequest(req)
const response = yield* cache.get(key)
const response = yield* cache.get(req)

if (response) {
if (DateTime.lessThan(timestamp, response.staleAt)) {
Expand All @@ -43,13 +35,7 @@ export const CachingHttpClient: Effect.Effect<
}),
)
}
return HttpClientResponse.fromWeb(
req,
new Response(response.response.body, {
status: response.response.status,
headers: Headers.fromInput(response.response.headers),
}),
)
return response.response
} else {
yield* Effect.logDebug('Cache miss')
}
Expand All @@ -60,7 +46,7 @@ export const CachingHttpClient: Effect.Effect<
Effect.tap(response => pipe(cache.set(response, DateTime.addDuration(timestamp, '10 seconds')), Effect.ignore)),
Effect.tap(response =>
Effect.gen(function* () {
const cachedValue = yield* cache.get(key)
const cachedValue = yield* cache.get(req)
if (cachedValue === undefined) {
return yield* Effect.logError('cache entry not found')
}
Expand All @@ -72,7 +58,7 @@ export const CachingHttpClient: Effect.Effect<
const cachedResponse = {
status: cachedValue.response.status,
headers: cachedValue.response.headers,
body: cachedValue.response.body,
body: yield* cachedValue.response.text,
}
const difference = diff(origResponse, cachedResponse)
function replacer(_: unknown, value: unknown) {
Expand All @@ -93,10 +79,3 @@ export const CachingHttpClient: Effect.Effect<

return HttpClient.makeWith(cachingBehaviour, Effect.succeed)
})

const keyForRequest = (request: HttpClientRequest.HttpClientRequest): HttpCache.CacheKey => {
const url = new URL(request.url)
url.search = UrlParams.toString(request.urlParams)

return url
}
26 changes: 22 additions & 4 deletions src/HttpCache.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Headers, UrlParams, type HttpClientRequest, type HttpClientResponse } from '@effect/platform'
import { Context, Effect, Layer, pipe, Schema, type DateTime } from 'effect'
import { Headers, HttpClientResponse, UrlParams, type HttpClientRequest } from '@effect/platform'
import { Context, Effect, Layer, Option, pipe, Schema, type DateTime } from 'effect'

interface CacheValue {
staleAt: DateTime.DateTime
Expand All @@ -19,7 +19,9 @@ const StoredResponseSchema = Schema.Struct({
export class HttpCache extends Context.Tag('HttpCache')<
HttpCache,
{
get: (key: CacheKey) => Effect.Effect<CacheValue | undefined>
get: (
request: HttpClientRequest.HttpClientRequest,
) => Effect.Effect<{ staleAt: DateTime.DateTime; response: HttpClientResponse.HttpClientResponse } | undefined>
set: (response: HttpClientResponse.HttpClientResponse, staleAt: DateTime.DateTime) => Effect.Effect<void, Error>
delete: (key: CacheKey) => Effect.Effect<void>
}
Expand All @@ -28,7 +30,23 @@ export class HttpCache extends Context.Tag('HttpCache')<
export const layer = Layer.sync(HttpCache, () => {
const cache = new Map<string, CacheValue>()
return {
get: key => Effect.succeed(cache.get(key.href)),
get: request =>
pipe(
cache.get(keyForRequest(request).href),
Option.fromNullable,
Option.map(({ staleAt, response }) => ({
staleAt,
response: HttpClientResponse.fromWeb(
request,
new Response(response.body, {
status: response.status,
headers: Headers.fromInput(response.headers),
}),
),
})),
Option.getOrUndefined,
Effect.succeed,
),
set: (response, staleAt) =>
pipe(
Effect.gen(function* () {
Expand Down

0 comments on commit e97d454

Please sign in to comment.