# 매니페스트가 선언하는 것
MongoIndexManifest.java:11 /**
MongoIndexManifest.java:12 * One declared index, with everything a diff or a review needs (design §18).
MongoIndexManifest.java:13 *
MongoIndexManifest.java:14 *
Two fields carry most of the weight. {@code expectedUsage} names the operations the index
MongoIndexManifest.java:15 * exists for, which is what makes "is this index still needed" answerable without guessing from
MongoIndexManifest.java:16 * production statistics. {@code metadataOwnership} says who created it, which is what keeps drift
MongoIndexManifest.java:17 * cleanup from proposing to drop an encryption or search index it did not declare.
MongoIndexManifest.java:18 *
MongoIndexManifest.java:19 *
Key order is preserved because it is part of the index's identity, not a presentation detail.
MongoIndexManifest.java:20 */
MongoIndexManifest.java:21 public record MongoIndexManifest(
MongoIndexManifest.java:22 String name,
MongoIndexManifest.java:23 List keys,
MongoIndexManifest.java:24 boolean unique,
MongoIndexManifest.java:25 boolean sparse,
MongoIndexManifest.java:26 boolean hidden,
MongoIndexManifest.java:27 boolean deprecated,
MongoIndexManifest.java:28 String partialFilterExpression,
MongoIndexManifest.java:29 String collationProfile,
MongoIndexManifest.java:30 Duration expireAfter,
MongoIndexManifest.java:31 String wildcardProjection,
MongoIndexManifest.java:32 boolean shardKeySupport,
MongoIndexManifest.java:33 Set expectedUsage,
MongoIndexManifest.java:34 String owner,
MongoIndexManifest.java:35 MongoMetadataOwnership metadataOwnership) {
MongoIndexManifest.java:36
MongoIndexManifest.java:37 public MongoIndexManifest {
MongoIndexManifest.java:38 Objects.requireNonNull(name, "name");
MongoIndexManifest.java:39 Objects.requireNonNull(keys, "keys");
MongoIndexManifest.java:40 Objects.requireNonNull(partialFilterExpression, "partialFilterExpression");
MongoIndexManifest.java:41 Objects.requireNonNull(collationProfile, "collationProfile");
MongoIndexManifest.java:42 Objects.requireNonNull(wildcardProjection, "wildcardProjection");
MongoIndexManifest.java:43 Objects.requireNonNull(expectedUsage, "expectedUsage");
MongoIndexManifest.java:44 Objects.requireNonNull(owner, "owner");
MongoIndexManifest.java:45 Objects.requireNonNull(metadataOwnership, "metadataOwnership");
# 비교용 뷰가 나르는 것
MongoIndexDescriptorView.java:6 /**
MongoIndexDescriptorView.java:7 * An index as it actually exists on the server (design §18).
MongoIndexDescriptorView.java:8 *
MongoIndexDescriptorView.java:9 * Read through the D4 admin client and reduced to the fields a diff can compare. Ownership is
MongoIndexDescriptorView.java:10 * inferred here rather than trusted from the manifest, because the whole purpose of the diff is to
MongoIndexDescriptorView.java:11 * find indexes the manifest does not know about — and some of those belong to encryption or search
MongoIndexDescriptorView.java:12 * and must never be proposed for deletion.
MongoIndexDescriptorView.java:13 */
MongoIndexDescriptorView.java:14 public record MongoIndexDescriptorView(
MongoIndexDescriptorView.java:15 String collection,
MongoIndexDescriptorView.java:16 String name,
MongoIndexDescriptorView.java:17 String keySignature,
MongoIndexDescriptorView.java:18 boolean unique,
MongoIndexDescriptorView.java:19 boolean hidden,
MongoIndexDescriptorView.java:20 MongoMetadataOwnership metadataOwnership) {
# 비교 엔진이 실제로 견주는 것
MongoIndexDiffEngine.java:25 /** Compares one collection's declared indexes with the observed ones. */
MongoIndexDiffEngine.java:26 public MongoIndexDiff compare(
MongoIndexDiffEngine.java:27 MongoCollectionManifest manifest, Collection observed) {
MongoIndexDiffEngine.java:28 Objects.requireNonNull(manifest, "manifest");
MongoIndexDiffEngine.java:29 Objects.requireNonNull(observed, "observed");
MongoIndexDiffEngine.java:30
MongoIndexDiffEngine.java:31 Map observedByName = new LinkedHashMap<>();
MongoIndexDiffEngine.java:32 for (MongoIndexDescriptorView view : observed) {
MongoIndexDiffEngine.java:33 observedByName.put(view.name(), view);
MongoIndexDiffEngine.java:34 }
MongoIndexDiffEngine.java:35
MongoIndexDiffEngine.java:36 List create = new ArrayList<>();
MongoIndexDiffEngine.java:37 List change = new ArrayList<>();
MongoIndexDiffEngine.java:38 List hide = new ArrayList<>();
MongoIndexDiffEngine.java:39 List dropCandidates = new ArrayList<>();
MongoIndexDiffEngine.java:40
MongoIndexDiffEngine.java:41 for (MongoIndexManifest declared : manifest.indexes()) {
MongoIndexDiffEngine.java:42 MongoIndexDescriptorView actual = observedByName.get(declared.name());
MongoIndexDiffEngine.java:43 if (actual == null) {
MongoIndexDiffEngine.java:44 if (!declared.deprecated()) {
MongoIndexDiffEngine.java:45 create.add(qualify(manifest, declared.name()));
MongoIndexDiffEngine.java:46 }
MongoIndexDiffEngine.java:47 continue;
MongoIndexDiffEngine.java:48 }
MongoIndexDiffEngine.java:49 if (!actual.keySignature().equals(declared.keySignature())
MongoIndexDiffEngine.java:50 || actual.unique() != declared.unique()) {
MongoIndexDiffEngine.java:51 // Same name, different definition: MongoDB will not silently re-create it, so a rebuild has
MongoIndexDiffEngine.java:52 // to be planned rather than discovered when a query starts scanning.
MongoIndexDiffEngine.java:53 change.add(qualify(manifest, declared.name()));
MongoIndexDiffEngine.java:54 }
MongoIndexDiffEngine.java:55 if (declared.hidden() && !actual.hidden()) {
MongoIndexDiffEngine.java:56 hide.add(qualify(manifest, declared.name()));
MongoIndexDiffEngine.java:57 }
MongoIndexDiffEngine.java:58 }
MongoIndexDiffEngine.java:59
MongoIndexDiffEngine.java:60 for (MongoIndexDescriptorView actual : observedByName.values()) {
MongoIndexDiffEngine.java:61 if (!actual.metadataOwnership().droppableByApplicationDrift()) {
MongoIndexDiffEngine.java:62 continue;
MongoIndexDiffEngine.java:63 }
MongoIndexDiffEngine.java:64 if (manifest.index(actual.name()).isEmpty()) {
MongoIndexDiffEngine.java:65 dropCandidates.add(qualify(manifest, actual.name()));
MongoIndexDiffEngine.java:66 }
MongoIndexDiffEngine.java:67 }
MongoIndexDiffEngine.java:68
MongoIndexDiffEngine.java:69 create.sort(String::compareTo);
MongoIndexDiffEngine.java:70 change.sort(String::compareTo);
한 줄에서 declared 값과 actual 값을 견주는 줄 : 3 개
MongoIndexDiffEngine.java:49 if (!actual.keySignature().equals(declared.keySignature())
MongoIndexDiffEngine.java:50 || actual.unique() != declared.unique()) {
MongoIndexDiffEngine.java:55 if (declared.hidden() && !actual.hidden()) {
[참고] 그 반복문에서 declared 나 actual 이 나오는 줄 전부 :
MongoIndexDiffEngine.java:42 MongoIndexDescriptorView actual = observedByName.get(declared.name());
MongoIndexDiffEngine.java:44 if (!declared.deprecated()) {
MongoIndexDiffEngine.java:45 create.add(qualify(manifest, declared.name()));
MongoIndexDiffEngine.java:49 if (!actual.keySignature().equals(declared.keySignature())
MongoIndexDiffEngine.java:50 || actual.unique() != declared.unique()) {
MongoIndexDiffEngine.java:53 change.add(qualify(manifest, declared.name()));
MongoIndexDiffEngine.java:55 if (declared.hidden() && !actual.hidden()) {
MongoIndexDiffEngine.java:56 hide.add(qualify(manifest, declared.name()));
# 뷰에 없어서 견줄 수 없는 요소
매니페스트 요소 : 14 개
뷰 요소 : 6 개
각 요소가 뷰에 있는가 :
name 뷰에 있음
keys 뷰에 없음
unique 뷰에 있음
sparse 뷰에 없음
hidden 뷰에 있음
deprecated 뷰에 없음
partialFilterExpression 뷰에 없음
collationProfile 뷰에 없음
expireAfter 뷰에 없음
wildcardProjection 뷰에 없음
shardKeySupport 뷰에 없음
expectedUsage 뷰에 없음
owner 뷰에 없음
metadataOwnership 뷰에 있음
[자기검증] 매니페스트 요소가 14 개가 아니면 실패 : 14 확인
# 빈 보고서가 무엇으로 읽히는가
MongoIndexDiff.java:1 package dev.caskeleton.adapter.outbound.mongo.schema.index;
MongoIndexDiff.java:2
MongoIndexDiff.java:3 import java.util.List;
MongoIndexDiff.java:4 import java.util.Objects;
MongoIndexDiff.java:5
MongoIndexDiff.java:6 /**
MongoIndexDiff.java:7 * The difference between declared and observed indexes (design §18).
MongoIndexDiff.java:8 *
MongoIndexDiff.java:9 * Every list is sorted so the diff is byte-identical for the same inputs. A CI artifact that
MongoIndexDiff.java:10 * reorders between runs cannot be diffed against the previous run, which is most of what an index
MongoIndexDiff.java:11 * drift report is for.
MongoIndexDiff.java:12 *
MongoIndexDiff.java:13 *
{@code dropCandidates} is named for what it is: a proposal that still has to pass deprecation,
MongoIndexDiff.java:14 * hiding, observation and approval before anything is dropped.
MongoIndexDiff.java:15 */
MongoIndexDiff.java:16 public record MongoIndexDiff(
MongoIndexDiff.java:17 List create, List change, List hide, List dropCandidates) {
MongoIndexDiff.java:18
MongoIndexDiff.java:19 public MongoIndexDiff {
MongoIndexDiff.java:20 Objects.requireNonNull(create, "create");
MongoIndexDiff.java:21 Objects.requireNonNull(change, "change");
MongoIndexDiff.java:22 Objects.requireNonNull(hide, "hide");
MongoIndexDiff.java:23 Objects.requireNonNull(dropCandidates, "dropCandidates");
MongoIndexDiff.java:24 create = List.copyOf(create);
MongoIndexDiff.java:25 change = List.copyOf(change);
MongoIndexDiff.java:26 hide = List.copyOf(hide);
MongoIndexDiff.java:27 dropCandidates = List.copyOf(dropCandidates);
MongoIndexDiff.java:28 }
MongoIndexDiff.java:29
MongoIndexDiff.java:30 /** A diff with no differences. */
MongoIndexDiff.java:31 public static MongoIndexDiff empty() {
MongoIndexDiff.java:32 return new MongoIndexDiff(List.of(), List.of(), List.of(), List.of());
MongoIndexDiff.java:33 }
MongoIndexDiff.java:34
MongoIndexDiff.java:35 /** True when declared and observed state already agree. */
MongoIndexDiff.java:36 public boolean isClean() {
MongoIndexDiff.java:37 return create.isEmpty() && change.isEmpty() && hide.isEmpty() && dropCandidates.isEmpty();
MongoIndexDiff.java:38 }
MongoIndexDiff.java:39
MongoIndexDiff.java:40 /** A stable, line-oriented rendering suitable for a CI artifact. */
MongoIndexDiff.java:41 public String render() {
MongoIndexDiff.java:42 StringBuilder report = new StringBuilder();
MongoIndexDiff.java:43 appendSection(report, "create", create);
MongoIndexDiff.java:44 appendSection(report, "change", change);
MongoIndexDiff.java:45 appendSection(report, "hide", hide);
MongoIndexDiff.java:46 appendSection(report, "drop-candidate", dropCandidates);
MongoIndexDiff.java:47 return report.toString();
MongoIndexDiff.java:48 }
MongoIndexDiff.java:49
MongoIndexDiffEngine 이 main 에 나오는 줄 : 1 개
MongoIndexDiffEngine.java:23 public final class MongoIndexDiffEngine {
[대조] 시험에서 그 엔진의 compare 를 부르는 줄 : 4 개
MongoIndexDiffEngineTest.java:30 MongoIndexDiff diff = engine.compare(manifest, observed);
MongoIndexDiffEngineTest.java:42 MongoIndexDiff diff = engine.compare(applicationManifest(), observed);
MongoIndexDiffEngineTest.java:49 MongoIndexDiff diff = engine.compare(applicationManifest(), List.of());
MongoIndexDiffEngineTest.java:61 MongoIndexDiff diff = engine.compare(applicationManifest(), observed);