{ "assetKey": "a10-f005-hyperloglog-merge-budget", "kind": "terminal", "command": "set -e\nD=$(mktemp -d); trap 'rm -rf \"$D\"' EXIT\nJAR=/shared/codebase/clean-architecture-backend-template/src/adapter/outbound/cache-redis/build/libs/cache-redis-0.0.1+21234e38cdb9.jar\ncat > \"$D/BudgetFillProbe.java\" <<'JAVA'\nimport dev.caskeleton.adapter.outbound.cache.redis.sdk.api.RedisDeploymentMode;\nimport dev.caskeleton.adapter.outbound.cache.redis.sdk.api.command.AdvancedOperationPermit;\nimport dev.caskeleton.adapter.outbound.cache.redis.sdk.api.command.MultiKeyPermit;\nimport dev.caskeleton.adapter.outbound.cache.redis.sdk.api.command.OperationBudget;\nimport dev.caskeleton.adapter.outbound.cache.redis.sdk.api.command.PersistentKeyPermit;\nimport dev.caskeleton.adapter.outbound.cache.redis.sdk.api.command.RedisPermitVerifier;\nimport dev.caskeleton.adapter.outbound.cache.redis.sdk.api.command.RedisPolicyAuthority;\nimport dev.caskeleton.adapter.outbound.cache.redis.sdk.api.key.RedisKeyRenderer;\nimport dev.caskeleton.adapter.outbound.cache.redis.sdk.api.key.RedisNamespace;\nimport dev.caskeleton.adapter.outbound.cache.redis.sdk.lettuce.operations.RedisOperationContext;\nimport dev.caskeleton.adapter.outbound.cache.redis.sdk.lettuce.operations.RedisOperationLimits;\n\npublic final class BudgetFillProbe {\n public static void main(String[] args) {\n RedisOperationLimits limits = RedisOperationLimits.defaults();\n RedisOperationContext ctx =\n new RedisOperationContext(\n new RedisNamespace(\"prod\", \"orders\", \"cache\"),\n new RedisKeyRenderer(512),\n new RedisPermitVerifier() {\n public void verify(AdvancedOperationPermit p, String s) {}\n public void verify(MultiKeyPermit p, String s) {}\n public void verify(PersistentKeyPermit p, String s) {}\n },\n new RedisPolicyAuthority() {\n public AdvancedOperationPermit issueAdvanced(String s) { return null; }\n public MultiKeyPermit issueMultiKey(String s) { return null; }\n public PersistentKeyPermit issuePersistentKey(String s) { return null; }\n },\n limits,\n RedisDeploymentMode.STANDALONE);\n\n long keyCeiling = dev.caskeleton.adapter.outbound.cache.redis.sdk.api.key\n .RedisKeyRules.MAX_KEY_BYTES;\n long pathMax = keyCeiling * limits.maxCollectionElements();\n\n System.out.println(\"[SDK가 채워 넣는 budget] collectionBudget(키 수, 요청 바이트)\");\n for (long bytes : new long[] {512L, 4_096L, pathMax}) {\n OperationBudget b = ctx.collectionBudget(8, bytes);\n System.out.printf(\n \" 요청 %-9d -> maxRequestBytes %-9d allowsRequestBytes(요청) %s%n\",\n bytes, b.maxRequestBytes(), b.allowsRequestBytes(bytes));\n }\n System.out.printf(\n \" 이 경로의 요청 최대 : 렌더된 키 %d 바이트 x 요소 천장 %d = %d 바이트%n\",\n keyCeiling, limits.maxCollectionElements(), pathMax);\n\n System.out.println();\n System.out.println(\"[호출자가 건네는 budget] 같은 요청을 거부할 수 있다\");\n OperationBudget declared = new OperationBudget(8, 4_096L, 65_536L, java.time.Duration.ofSeconds(2));\n System.out.printf(\n \" maxRequestBytes %d, 요청 8192 -> allowsRequestBytes %s%n\",\n declared.maxRequestBytes(), declared.allowsRequestBytes(8_192L));\n\n System.out.println();\n System.out.println(\"[채워 넣은 budget이 실제로 거부하는 것]\");\n OperationBudget b = ctx.collectionBudget(limits.maxCollectionElements(), 1_024L);\n System.out.printf(\" 요소 %d개 -> 통과, maxReplyBytes %d, timeout %s%n\",\n limits.maxCollectionElements(), b.maxReplyBytes(), b.timeout());\n try {\n ctx.collectionBudget(limits.maxCollectionElements() + 1, 1_024L);\n System.out.println(\" 요소 1001개 -> 통과\");\n } catch (RuntimeException e) {\n System.out.println(\" 요소 1001개 -> \" + e.getClass().getSimpleName() + \": \" + e.getMessage());\n }\n\n System.out.println();\n System.out.println(\"[PFCOUNT/PFMERGE가 선언하는 expectedReplyBytes] 0\");\n System.out.println(\" allowsReplyBytes(0) = \" + b.allowsReplyBytes(0L));\n }\n}\nJAVA\njava -version 2>&1 | head -1\njavac -encoding UTF-8 -cp \"$JAR\" -d \"$D\" \"$D/BudgetFillProbe.java\"\njava -Dstdout.encoding=UTF-8 -cp \"$JAR:$D\" BudgetFillProbe\n", "cwd": "/shared/codebase/clean-architecture-backend-template/src/adapter/outbound/cache-redis", "exitCode": 0, "executedAt": "2026-09-02T12:53:03+00:00", "sourceRevision": "21234e38cdb9a926cbc92bb97a2aee2e4a7d2916", "raw": "evidence/raw/a10-f005-hyperloglog-merge-budget.txt", "svg": "evidence/rendered/a10-f005-hyperloglog-merge-budget.svg", "rawSha256": "81684a8a2afc5b3e2d02421c8cdaf46c1e345ba8160c0beb82a942f25446dc19", "lines": 16, "redaction": "none — 밀폐 탐침 실행 출력, 자격증명 없음" }