(file: UserFile, value: string, ttlSeconds: number)
| 217 | } |
| 218 | }, |
| 219 | async set(file: UserFile, value: string, ttlSeconds: number) { |
| 220 | const key = getFullCacheKey(executionId, file) |
| 221 | const valueBytes = Buffer.byteLength(value, 'utf8') |
| 222 | try { |
| 223 | if (!executionId) { |
| 224 | await redis.set(key, value, 'EX', ttlSeconds) |
| 225 | return |
| 226 | } |
| 227 | |
| 228 | const limits = getExecutionRedisBudgetLimits() |
| 229 | if (valueBytes > limits.maxSingleWriteBytes) { |
| 230 | throw new ExecutionResourceLimitError({ |
| 231 | resource: 'redis_key_bytes', |
| 232 | attemptedBytes: valueBytes, |
| 233 | limitBytes: limits.maxSingleWriteBytes, |
| 234 | }) |
| 235 | } |
| 236 | const cacheTtlSeconds = Math.max(ttlSeconds, limits.ttlSeconds) |
| 237 | const budgetReservation: ExecutionRedisBudgetReservation = { |
| 238 | executionId, |
| 239 | userId: options.userId, |
| 240 | category: 'base64_cache', |
| 241 | operation: 'set_base64_cache', |
| 242 | bytes: valueBytes, |
| 243 | logger, |
| 244 | } |
| 245 | const budgetKeys = getExecutionRedisBudgetKeys(budgetReservation) |
| 246 | const result = (await redis.eval( |
| 247 | SET_BASE64_CACHE_SCRIPT, |
| 248 | 2 + budgetKeys.length, |
| 249 | key, |
| 250 | getBudgetIndexKey(executionId), |
| 251 | ...budgetKeys, |
| 252 | value, |
| 253 | cacheTtlSeconds, |
| 254 | getFileCacheKey(file), |
| 255 | serializeBudgetEntry({ bytes: valueBytes, userId: options.userId }), |
| 256 | valueBytes, |
| 257 | limits.maxExecutionBytes, |
| 258 | limits.maxUserBytes, |
| 259 | limits.ttlSeconds |
| 260 | )) as [number, string, number | string | null] |
| 261 | const [allowed, resource, current] = result |
| 262 | if (allowed !== 1) { |
| 263 | throw new ExecutionResourceLimitError({ |
| 264 | resource: |
| 265 | resource === 'user_redis_bytes' ? 'user_redis_bytes' : 'execution_redis_bytes', |
| 266 | attemptedBytes: valueBytes, |
| 267 | currentBytes: Number(current ?? 0), |
| 268 | limitBytes: |
| 269 | resource === 'user_redis_bytes' ? limits.maxUserBytes : limits.maxExecutionBytes, |
| 270 | }) |
| 271 | } |
| 272 | } catch (error) { |
| 273 | if (isExecutionResourceLimitError(error)) { |
| 274 | throw error |
| 275 | } |
| 276 | logger.warn(`[${options.requestId}] Redis set failed, skipping cache`, error) |
nothing calls this directly
no test coverage detected