({ prefix }: StorageConfig, dir: string)
| 164 | * and should therefore be as fast as the Memory Store. |
| 165 | */ |
| 166 | export function makeDiskStore({ prefix }: StorageConfig, dir: string) { |
| 167 | return Effect.sync(() => { |
| 168 | if (!fs.existsSync(dir)) { |
| 169 | fs.mkdirSync(dir) |
| 170 | } |
| 171 | return { |
| 172 | make: Effect.fnUntraced(function*<IdKey extends keyof Encoded, Encoded extends FieldValues, R, E>( |
| 173 | name: string, |
| 174 | idKey: IdKey, |
| 175 | seed?: Effect.Effect<Iterable<Encoded>, E, R>, |
| 176 | config?: StoreConfig<Encoded> |
| 177 | ) { |
| 178 | const primary = yield* makeDiskStoreInt(prefix, idKey, "primary", dir, name, seed, config?.defaultValues).pipe( |
| 179 | Effect.orDie |
| 180 | ) |
| 181 | const stores = new Map<string, Store<IdKey, Encoded>>([["primary", primary]]) |
| 182 | const ctx = yield* Effect.context<R>() |
| 183 | const semaphores = new Map<string, Semaphore.Semaphore>() |
| 184 | const getSem = (ns: string) => { |
| 185 | let sem = semaphores.get(ns) |
| 186 | if (!sem) { |
| 187 | sem = Semaphore.makeUnsafe(1) |
| 188 | semaphores.set(ns, sem) |
| 189 | } |
| 190 | return sem |
| 191 | } |
| 192 | const ensureStore = (namespace: string) => |
| 193 | getSem(namespace).withPermits(1)( |
| 194 | Effect.suspend(() => { |
| 195 | const existing = stores.get(namespace) |
| 196 | if (existing) return Effect.succeed(existing) |
| 197 | if (config?.allowNamespace && !config.allowNamespace(namespace)) { |
| 198 | throw new Error(`Namespace ${namespace} not allowed!`) |
| 199 | } |
| 200 | return makeDiskStoreInt<IdKey, Encoded, R, E>( |
| 201 | prefix, |
| 202 | idKey, |
| 203 | namespace, |
| 204 | dir, |
| 205 | name, |
| 206 | seed, |
| 207 | config?.defaultValues |
| 208 | ) |
| 209 | .pipe( |
| 210 | Effect.orDie, |
| 211 | Effect.provide(ctx), |
| 212 | Effect.tap((store) => Effect.sync(() => stores.set(namespace, store))) |
| 213 | ) |
| 214 | }) |
| 215 | ) |
| 216 | const getStore = !config?.allowNamespace |
| 217 | ? Effect.succeed(primary) |
| 218 | : storeId.pipe(Effect.flatMap((namespace) => ensureStore(namespace))) |
| 219 | |
| 220 | const s: Store<IdKey, Encoded> = { |
| 221 | seedNamespace: (namespace) => ensureStore(namespace).pipe(Effect.asVoid), |
| 222 | all: Effect.flatMap(getStore, (_) => _.all), |
| 223 | find: (...args) => Effect.flatMap(getStore, (_) => _.find(...args)), |
no test coverage detected
searching dependent graphs…