# 이 실패를 위한 어휘 MongoFailureCategory.java:3 /** MongoFailureCategory.java:4 * Stable parent category of a failure (design §15). MongoFailureCategory.java:5 * MongoFailureCategory.java:6 *

Server codes and driver error labels change between releases; this category does not. It is MongoFailureCategory.java:7 * the value that appears in metrics and dashboards, which is why an unrecognised server code maps MongoFailureCategory.java:8 * to {@link #UNCLASSIFIED} rather than inventing a new category at runtime and blowing up metric MongoFailureCategory.java:9 * cardinality. MongoFailureCategory.java:10 */ MongoFailureCategory.java:63 MongoFailureCategory.java:64 /** The platform refused the operation locally before contacting a server. */ MongoFailureCategory.java:65 OPERATION_REJECTED, MongoFailureCategory.java:66 MongoFailureCategory.java:67 /** The stored document's schema version is outside the supported range. */ MongoFailureCategory.java:68 SCHEMA_VERSION_UNSUPPORTED, MongoFailureCategory.java:69 MongoFailureCategory.java:70 /** A recognised failure with no more specific stable category. */ MongoFailureCategory.java:71 UNCLASSIFIED MongoFailureCategory.java:72 } MongoDataSchemaUnsupportedException.java:5 /** MongoDataSchemaUnsupportedException.java:6 * A stored document's schema version is outside the supported range (design §12.2). MongoDataSchemaUnsupportedException.java:7 * MongoDataSchemaUnsupportedException.java:8 *

Raised before domain deserialization, which is the whole value: a document written by a newer MongoDataSchemaUnsupportedException.java:9 * release, or one left behind by a retired version, must not be silently coerced into the current MongoDataSchemaUnsupportedException.java:10 * shape. Versions are integers and carry no data, so both are safe to name in the message. MongoDataSchemaUnsupportedException.java:11 */ MongoDataSchemaUnsupportedException.java:12 public final class MongoDataSchemaUnsupportedException extends MongoPersistenceException { MongoDataSchemaUnsupportedException.java:13 MongoDataSchemaUnsupportedException.java:14 @Serial private static final long serialVersionUID = 1L; MongoDataSchemaUnsupportedException.java:15 MongoDataSchemaUnsupportedException.java:16 private final int documentVersion; MongoDataSchemaUnsupportedException.java:17 MongoDataSchemaUnsupportedException.java:18 private final int minimumSupported; MongoDataSchemaUnsupportedException.java:19 MongoDataSchemaUnsupportedException.java:20 private final int currentVersion; MongoDataSchemaUnsupportedException.java:21 MongoDataSchemaUnsupportedException.java:22 public MongoDataSchemaUnsupportedException( MongoDataSchemaUnsupportedException.java:23 MongoFailureContext failureContext, MongoDataSchemaUnsupportedException.java:24 int documentVersion, MongoDataSchemaUnsupportedException.java:25 int minimumSupported, MongoDataSchemaUnsupportedException.java:26 int currentVersion) { MongoDataSchemaUnsupportedException.java:27 super( MongoDataSchemaUnsupportedException.java:28 "stored schema version " MongoDataSchemaUnsupportedException.java:29 + documentVersion MongoDataSchemaUnsupportedException.java:30 + " is outside the supported range [" MongoDataSchemaUnsupportedException.java:31 + minimumSupported MongoDataSchemaUnsupportedException.java:32 + ", " MongoDataSchemaUnsupportedException.java:33 + currentVersion MongoDataSchemaUnsupportedException.java:34 + "]", MongoDataSchemaUnsupportedException.java:35 failureContext); MongoDataSchemaUnsupportedException.java:36 this.documentVersion = documentVersion; MongoDataSchemaUnsupportedException.java:37 this.minimumSupported = minimumSupported; MongoDataSchemaUnsupportedException.java:38 this.currentVersion = currentVersion; MongoDataSchemaUnsupportedException.java:39 } MongoDataSchemaUnsupportedException.java:40 MongoDataSchemaUnsupportedException.java:41 /** The version found on the stored document. */ MongoDataSchemaUnsupportedException.java:42 public int documentVersion() { MongoDataSchemaUnsupportedException.java:43 return documentVersion; MongoDataSchemaUnsupportedException.java:44 } MongoDataSchemaUnsupportedException.java:45 MongoDataSchemaUnsupportedException.java:46 /** The oldest version this release can still read. */ MongoDataSchemaUnsupportedException.java:47 public int minimumSupported() { MongoDataSchemaUnsupportedException.java:48 return minimumSupported; MongoDataSchemaUnsupportedException.java:49 } MongoDataSchemaUnsupportedException.java:50 MongoDataSchemaUnsupportedException.java:51 /** The version this release writes. */ MongoDataSchemaUnsupportedException.java:52 public int currentVersion() { MongoDataSchemaUnsupportedException.java:53 return currentVersion; MongoDataSchemaUnsupportedException.java:54 } # 프로덕션 생성 지점 전수 MongoSchemaVersionPolicy.java:85 return new MongoDataSchemaUnsupportedException( DefaultMongoFailureTranslator.java:111 new MongoDataSchemaUnsupportedException(failureContext, -1, -1, -1); # 버전을 아는 쪽 MongoSchemaVersionPolicy.java:82 private MongoDataSchemaUnsupportedException unsupported(DocumentSchemaVersion version) { MongoSchemaVersionPolicy.java:83 MongoFailureContext context = MongoSchemaVersionPolicy.java:84 MongoFailureContext.rejected(new MongoOperationName("schema.version-check")); MongoSchemaVersionPolicy.java:85 return new MongoDataSchemaUnsupportedException( MongoSchemaVersionPolicy.java:86 context, version.value(), range.minimumSupported().value(), range.current().value()); MongoSchemaVersionPolicy.java:87 } 그 context 가 무엇을 담는가 : MongoFailureContext.java:135 public static MongoFailureContext rejected(MongoOperationName operationName) { MongoFailureContext.java:136 return new MongoFailureContext( MongoFailureContext.java:137 MongoOperationScope.ofOperation(operationName), MongoFailureContext.java:138 MongoOperationType.UNKNOWN, MongoFailureContext.java:139 MongoConsistencyProfile.PRIMARY_LOCAL, MongoFailureContext.java:140 MongoFailureCategory.OPERATION_REJECTED, MongoFailureContext.java:141 MongoExecutionOutcome.NOT_SENT, MongoFailureContext.java:142 false, MongoFailureContext.java:143 false, MongoFailureContext.java:144 Set.of(), MongoFailureContext.java:145 "", MongoFailureContext.java:146 1, MongoFailureContext.java:147 Duration.ZERO, MongoFailureContext.java:148 ""); MongoFailureContext.java:149 } # 전용 category 를 붙이는 쪽 DefaultMongoFailureTranslator.java:88 elapsed, DefaultMongoFailureTranslator.java:89 ""); DefaultMongoFailureTranslator.java:90 DefaultMongoFailureTranslator.java:91 return switch (classification.category()) { DefaultMongoFailureTranslator.java:92 case DUPLICATE_KEY -> new MongoDuplicateKeyException(failureContext); DefaultMongoFailureTranslator.java:93 case SCHEMA_VALIDATION -> new MongoSchemaValidationException(failureContext); DefaultMongoFailureTranslator.java:94 case OPTIMISTIC_CONFLICT -> new MongoOptimisticConflictException(failureContext); DefaultMongoFailureTranslator.java:95 case WRITE_CONFLICT -> new MongoWriteConflictException(failureContext); DefaultMongoFailureTranslator.java:96 case TRANSACTION_TRANSIENT -> new MongoTransactionTransientException(failureContext); DefaultMongoFailureTranslator.java:97 case TRANSACTION_COMMIT_UNKNOWN -> DefaultMongoFailureTranslator.java:98 new MongoTransactionCommitUnknownException( DefaultMongoFailureTranslator.java:99 failureContext, "read the transaction record, version or idempotency key"); DefaultMongoFailureTranslator.java:100 case WRITE_CONCERN -> new MongoWriteConcernException(failureContext); DefaultMongoFailureTranslator.java:101 case READ_CONCERN -> new MongoReadConcernException(failureContext); DefaultMongoFailureTranslator.java:102 case SERVER_SELECTION -> new MongoServerSelectionException(failureContext); DefaultMongoFailureTranslator.java:103 case CONNECTION -> new MongoConnectionException(failureContext); DefaultMongoFailureTranslator.java:104 case TIMEOUT -> new MongoTimeoutException(failureContext); DefaultMongoFailureTranslator.java:105 case CURSOR -> new MongoCursorException(failureContext); DefaultMongoFailureTranslator.java:106 case DOCUMENT_TOO_LARGE -> new MongoDocumentTooLargeException(failureContext, -1L, -1L); DefaultMongoFailureTranslator.java:107 case SHARD_ROUTING -> new MongoShardRoutingException(failureContext); DefaultMongoFailureTranslator.java:108 case RESUME -> new MongoResumeException(failureContext); DefaultMongoFailureTranslator.java:109 case ENCRYPTION -> new MongoEncryptionException(failureContext); DefaultMongoFailureTranslator.java:110 case SCHEMA_VERSION_UNSUPPORTED -> DefaultMongoFailureTranslator.java:111 new MongoDataSchemaUnsupportedException(failureContext, -1, -1, -1); DefaultMongoFailureTranslator.java:112 // Bulk partial failure and local rejection are raised by the layers that own their detail — DefaultMongoFailureTranslator.java:113 // per-item results and the guardrail that refused — so a failure that reaches translation DefaultMongoFailureTranslator.java:114 // carrying either category is one this release does not recognise. DefaultMongoFailureTranslator.java:115 case BULK_PARTIAL_FAILURE, OPERATION_REJECTED, UNCLASSIFIED -> DefaultMongoFailureTranslator.java:116 new MongoUnclassifiedFailureException(failureContext); DefaultMongoFailureTranslator.java:117 }; DefaultMongoFailureTranslator.java:118 } # 그 case 에 도달할 수 있는가 SCHEMA_VERSION_UNSUPPORTED 가 저장소 전체에 나오는 줄 : 2 개 MongoFailureCategory.java:68 SCHEMA_VERSION_UNSUPPORTED, DefaultMongoFailureTranslator.java:110 case SCHEMA_VERSION_UNSUPPORTED -> [대조] OPERATION_REJECTED 는 : 4 개 분류기가 category 를 정하는 자리 전부 : DefaultMongoFailureClassifier.java:24 /** Server codes whose meaning the platform maps to a stable category. */ DefaultMongoFailureClassifier.java:25 private static final Map CATEGORY_BY_CODE = DefaultMongoFailureClassifier.java:26 Map.ofEntries( DefaultMongoFailureClassifier.java:27 Map.entry(11000, MongoFailureCategory.DUPLICATE_KEY), DefaultMongoFailureClassifier.java:28 Map.entry(11001, MongoFailureCategory.DUPLICATE_KEY), DefaultMongoFailureClassifier.java:29 Map.entry(12582, MongoFailureCategory.DUPLICATE_KEY), DefaultMongoFailureClassifier.java:30 Map.entry(121, MongoFailureCategory.SCHEMA_VALIDATION), DefaultMongoFailureClassifier.java:31 Map.entry(112, MongoFailureCategory.WRITE_CONFLICT), DefaultMongoFailureClassifier.java:32 Map.entry(64, MongoFailureCategory.WRITE_CONCERN), DefaultMongoFailureClassifier.java:33 Map.entry(79, MongoFailureCategory.WRITE_CONCERN), DefaultMongoFailureClassifier.java:34 Map.entry(100, MongoFailureCategory.WRITE_CONCERN), DefaultMongoFailureClassifier.java:35 Map.entry(148, MongoFailureCategory.READ_CONCERN), DefaultMongoFailureClassifier.java:36 Map.entry(246, MongoFailureCategory.READ_CONCERN), DefaultMongoFailureClassifier.java:37 Map.entry(133, MongoFailureCategory.SERVER_SELECTION), DefaultMongoFailureClassifier.java:38 Map.entry(6, MongoFailureCategory.CONNECTION), DefaultMongoFailureClassifier.java:39 Map.entry(7, MongoFailureCategory.CONNECTION), DefaultMongoFailureClassifier.java:40 Map.entry(9001, MongoFailureCategory.CONNECTION), DefaultMongoFailureClassifier.java:41 Map.entry(89, MongoFailureCategory.TIMEOUT), DefaultMongoFailureClassifier.java:42 Map.entry(50, MongoFailureCategory.TIMEOUT), DefaultMongoFailureClassifier.java:43 Map.entry(262, MongoFailureCategory.TIMEOUT), DefaultMongoFailureClassifier.java:44 Map.entry(43, MongoFailureCategory.CURSOR), DefaultMongoFailureClassifier.java:45 Map.entry(237, MongoFailureCategory.CURSOR), DefaultMongoFailureClassifier.java:46 Map.entry(10334, MongoFailureCategory.DOCUMENT_TOO_LARGE), DefaultMongoFailureClassifier.java:47 Map.entry(17420, MongoFailureCategory.DOCUMENT_TOO_LARGE), DefaultMongoFailureClassifier.java:48 Map.entry(63, MongoFailureCategory.SHARD_ROUTING), DefaultMongoFailureClassifier.java:49 Map.entry(13388, MongoFailureCategory.SHARD_ROUTING), DefaultMongoFailureClassifier.java:50 Map.entry(286, MongoFailureCategory.RESUME), DefaultMongoFailureClassifier.java:51 Map.entry(280, MongoFailureCategory.RESUME), DefaultMongoFailureClassifier.java:52 Map.entry(31, MongoFailureCategory.ENCRYPTION)); DefaultMongoFailureClassifier.java:86 // Labels first: the server's own recoverability statement outranks any code table, and these DefaultMongoFailureClassifier.java:87 // two labels are the ones whose correct responses are opposite. DefaultMongoFailureClassifier.java:88 if (failure.hasLabel(MongoDriverFailureView.UNKNOWN_TRANSACTION_COMMIT_RESULT)) { DefaultMongoFailureClassifier.java:89 return MongoFailureClassification.commitUnknown(); DefaultMongoFailureClassifier.java:90 } DefaultMongoFailureClassifier.java:91 if (failure.hasLabel(MongoDriverFailureView.TRANSIENT_TRANSACTION_ERROR)) { DefaultMongoFailureClassifier.java:92 return MongoFailureClassification.transientTransaction(); DefaultMongoFailureClassifier.java:93 } DefaultMongoFailureClassifier.java:94 if (failure.hasLabel(MongoDriverFailureView.NO_WRITES_PERFORMED)) { DefaultMongoFailureClassifier.java:95 return new MongoFailureClassification( DefaultMongoFailureClassifier.java:96 categoryOf(failure), MongoExecutionOutcome.NO_WRITE_PERFORMED, MongoRetryScope.NONE); DefaultMongoFailureClassifier.java:97 } DefaultMongoFailureClassifier.java:98 DefaultMongoFailureClassifier.java:99 MongoFailureCategory category = categoryOf(failure); DefaultMongoFailureClassifier.java:100 DefaultMongoFailureClassifier.java:101 if (phase != null) { DefaultMongoFailureClassifier.java:102 if (phase.nothingWasSent()) { DefaultMongoFailureClassifier.java:103 // Nothing reached a server, so nothing was applied. A server-selection timeout carries no DefaultMongoFailureClassifier.java:104 // label and often no code, and used to land in UNCLASSIFIED and be treated as terminal — DefaultMongoFailureClassifier.java:105 // the one case where retrying is unambiguously safe. DefaultMongoFailureClassifier.java:106 return MongoFailureClassification.retryableOperation( DefaultMongoFailureClassifier.java:107 category == MongoFailureCategory.UNCLASSIFIED DefaultMongoFailureClassifier.java:108 ? MongoFailureCategory.SERVER_SELECTION DefaultMongoFailureClassifier.java:109 : category); DefaultMongoFailureClassifier.java:110 } DefaultMongoFailureClassifier.java:111 if (phase == MongoFailurePhase.TRANSACTION_COMMIT && failure.outcomeIsUnknown()) { DefaultMongoFailureClassifier.java:112 return MongoFailureClassification.commitUnknown(); DefaultMongoFailureClassifier.java:113 } DefaultMongoFailureClassifier.java:114 if (phase == MongoFailurePhase.TRANSACTION_BODY && failure.outcomeIsUnknown()) { DefaultMongoFailureClassifier.java:115 // The body has not committed, so replaying the whole transaction is the correct scope — DefaultMongoFailureClassifier.java:116 // and the correct scope is exactly what an ambiguous-write verdict would have denied. DefaultMongoFailureClassifier.java:117 return MongoFailureClassification.transientTransaction(); DefaultMongoFailureClassifier.java:118 } DefaultMongoFailureClassifier.java:119 if (operationType != null && isRead(operationType) && !isDefinitelyUnapplied(failure)) { DefaultMongoFailureClassifier.java:120 // A read that failed changed nothing whatever phase it was in. Reporting it as an DefaultMongoFailureClassifier.java:150 private static MongoFailureCategory categoryOf(MongoDriverFailureView failure) { DefaultMongoFailureClassifier.java:151 if (!failure.hasServerCode()) { DefaultMongoFailureClassifier.java:152 return failure.hasLabel(MongoDriverFailureView.RETRYABLE_WRITE_ERROR) DefaultMongoFailureClassifier.java:153 ? MongoFailureCategory.CONNECTION DefaultMongoFailureClassifier.java:154 : MongoFailureCategory.UNCLASSIFIED; DefaultMongoFailureClassifier.java:155 } DefaultMongoFailureClassifier.java:156 return CATEGORY_BY_CODE.getOrDefault(failure.serverCode(), MongoFailureCategory.UNCLASSIFIED); DefaultMongoFailureClassifier.java:157 } [대조] 같은 정규식을 MongoFailureContextTest 에 걸면 : 1 개 # 이 모듈에서 살아 있는 다른 스키마 실패 경로 MongoFailureContext.java:151 /** MongoFailureContext.java:152 * A stored document that does not match the schema this release expects. MongoFailureContext.java:153 * MongoFailureContext.java:154 *

Nothing was written, so the outcome is {@code NO_WRITE_PERFORMED} rather than {@code MongoFailureContext.java:155 * NOT_SENT}: the read did reach the server, and what came back is unusable. MongoFailureContext.java:156 */ MongoFailureContext.java:157 public static MongoFailureContext schemaMismatch(MongoOperationName operationName) { MongoFailureContext.java:158 return new MongoFailureContext( MongoFailureContext.java:159 MongoOperationScope.ofOperation(operationName), MongoFailureContext.java:160 MongoOperationType.FIND, MongoFailureContext.java:161 MongoConsistencyProfile.PRIMARY_LOCAL, MongoFailureContext.java:162 MongoFailureCategory.SCHEMA_VALIDATION, MongoFailureContext.java:163 MongoExecutionOutcome.NO_WRITE_PERFORMED, MongoFailureContext.java:164 false, MongoFailureContext.java:165 false, MongoFailureContext.java:166 Set.of(), MongoFailureContext.java:167 "", MongoFailureContext.java:168 1, MongoFailureContext.java:169 Duration.ZERO, MongoFailureContext.java:170 ""); MongoFailureContext.java:171 } MongoFailureContext.java:172 그 팩터리를 부르는 자리 : MongoFailureContext.java:157 public static MongoFailureContext schemaMismatch(MongoOperationName operationName) { PolicyAwareMongoTypeMapper.java:112 dev.caskeleton.adapter.outbound.mongo.api.error.MongoFailureContext.schemaMismatch( PolicyAwareMongoTypeMapper.java:185 MongoFailureContext.schemaMismatch(READ_OPERATION))); PolicyAwareMongoTypeMapper.java:192 throw new MongoSchemaValidationException(MongoFailureContext.schemaMismatch(READ_OPERATION)); # 두 생성 지점이 조립되는가 new MongoSchemaVersionPolicy 를 부르는 main 줄 : 0 개 그 타입이 main 에 나오는 자리 전부 : MongoSchemaVersionPolicy.java:17 public final class MongoSchemaVersionPolicy { MongoSchemaVersionPolicy.java:22 public MongoSchemaVersionPolicy( MongoSchemaVersionPolicy.java:29 public MongoSchemaVersionPolicy(MongoSchemaVersionRange range, boolean legacyReadsEnabled) { [대조] new MongoSchemaVersionPolicy 를 부르는 시험 줄 : 6 개 DefaultMongoFailureTranslator 를 빈으로 만드는 main 줄 : 2 개 MongoPlatformAutoConfiguration.java:93 return new DefaultMongoFailureTranslator(classifier); DefaultMongoFailureTranslator.java:47 return new DefaultMongoFailureTranslator(new DefaultMongoFailureClassifier()); # 같은 모양이 하나 더 MongoDocumentTooLargeException.java:26 } MongoDocumentTooLargeException.java:27 MongoDocumentTooLargeException.java:28 /** Estimated serialized size. A size, not content: safe to log. */ MongoDocumentTooLargeException.java:29 public long estimatedBytes() { MongoDocumentTooLargeException.java:30 return estimatedBytes; MongoDocumentTooLargeException.java:31 } MongoDocumentTooLargeException.java:32 MongoDocumentTooLargeException.java:33 /** The configured ceiling that was exceeded. */ MongoDocumentTooLargeException.java:34 public long budgetBytes() { MongoDocumentTooLargeException.java:35 return budgetBytes; MongoDocumentTooLargeException.java:36 } # 그 정책을 검사하는 시험이 무엇을 단언하는가 MongoSchemaVersionPolicyTest.java:4 import static org.assertj.core.api.Assertions.assertThatThrownBy; MongoSchemaVersionPolicyTest.java:15 void rejectsFutureVersion() { MongoSchemaVersionPolicyTest.java:20 assertThatThrownBy(() -> policy.requireReadable(new DocumentSchemaVersion(5))) MongoSchemaVersionPolicyTest.java:21 .isInstanceOf(MongoDataSchemaUnsupportedException.class); MongoSchemaVersionPolicyTest.java:25 void rejectsRetiredVersion() { MongoSchemaVersionPolicyTest.java:30 assertThatThrownBy(() -> policy.requireReadable(new DocumentSchemaVersion(1))) MongoSchemaVersionPolicyTest.java:31 .isInstanceOf(MongoDataSchemaUnsupportedException.class); MongoSchemaVersionPolicyTest.java:35 void missingVersionIsLegacyOnlyWhenTheCollectionAllowsIt() { MongoSchemaVersionPolicyTest.java:43 assertThat(permissive.resolveMissingVersion()).isEqualTo(DocumentSchemaVersion.LEGACY_V0); MongoSchemaVersionPolicyTest.java:44 assertThatThrownBy(strict::resolveMissingVersion) MongoSchemaVersionPolicyTest.java:45 .isInstanceOf(MongoDataSchemaUnsupportedException.class); MongoSchemaVersionPolicyTest.java:49 void newWritesAlwaysUseTheCurrentVersion() { MongoSchemaVersionPolicyTest.java:54 assertThat(policy.writeVersion()).isEqualTo(new DocumentSchemaVersion(4)); MongoSchemaVersionPolicyTest.java:58 void readingAnOlderSupportedVersionIsAMeteredConversion() { MongoSchemaVersionPolicyTest.java:63 assertThat(policy.requiresReadTimeConversion(new DocumentSchemaVersion(3))).isTrue(); MongoSchemaVersionPolicyTest.java:64 assertThat(policy.requiresReadTimeConversion(new DocumentSchemaVersion(4))).isFalse(); MongoSchemaVersionPolicyTest.java:68 void aNegativeVersionIsNotAVersion() { MongoSchemaVersionPolicyTest.java:69 assertThatThrownBy(() -> new DocumentSchemaVersion(-1)) MongoSchemaVersionPolicyTest.java:70 .isInstanceOf(IllegalArgumentException.class); 그 시험이 category 나 세 버전 값을 단언하는 줄 : 0 개