# 이 타입이 존재하는 이유 BoundScopedOperations.java:12 /** BoundScopedOperations.java:13 * {@link ScopedMongoOperations} over one physical collection. BoundScopedOperations.java:14 * BoundScopedOperations.java:15 *
Every method passes the collection this scope was built with. That is the whole implementation BoundScopedOperations.java:16 * and the whole point: a caller cannot supply a different one, so the registered collection profile BoundScopedOperations.java:17 * and any tenant boundary derived from it hold without the caller having to cooperate. BoundScopedOperations.java:18 * BoundScopedOperations.java:19 *
Every query-shaped method also carries the operation's deadline as {@code maxTimeMS}, and that BoundScopedOperations.java:20 * is the difference between a deadline and a report about one. The blocking executor could only BoundScopedOperations.java:21 * measure elapsed time after the callback returned — a Java callback cannot be interrupted mid BoundScopedOperations.java:22 * driver call — so an operation that ran past its budget was detected, never stopped. Sent to the BoundScopedOperations.java:23 * server, the same number ends the work. BoundScopedOperations.java:24 * BoundScopedOperations.java:25 *
It applies to the methods that take a {@link Query} or an {@link Aggregation}, because those BoundScopedOperations.java:26 * are the ones the server can cut short. {@code insert} carries no query to attach it to. BoundScopedOperations.java:27 */ 그 데드라인이 실제로 붙는 자리 : BoundScopedOperations.java:19 *
Every query-shaped method also carries the operation's deadline as {@code maxTimeMS}, and that BoundScopedOperations.java:53 return query.maxTimeMsec(timeout.toMillis()); BoundScopedOperations.java:98 .maxTime(timeout) BoundScopedOperations.java:48 *
Mutates the caller's query rather than copying it, which is what Spring Data's own fluent
BoundScopedOperations.java:49 * API does; a copy would silently drop any hint, collation or read preference the caller set.
BoundScopedOperations.java:50 */
BoundScopedOperations.java:51 private Query bounded(Query query) {
BoundScopedOperations.java:52 Objects.requireNonNull(query, "query");
BoundScopedOperations.java:53 return query.maxTimeMsec(timeout.toMillis());
BoundScopedOperations.java:54 }
BoundScopedOperations.java:55
BoundScopedOperations.java:56 @Override
BoundScopedOperations.java:92
BoundScopedOperations.java:93 @Override
BoundScopedOperations.java:94 public Scoped: no method takes a collection name, so the check {@link #collection(String)} performs
MongoCollectionAccess.java:29 * cannot be bypassed by not calling it. The previous {@code MongoOperations} accessor could reach
MongoCollectionAccess.java:30 * any collection in the database.
MongoCollectionAccess.java:31 */
MongoCollectionAccess.java:32 ScopedMongoOperations scoped();
MongoCollectionAccess.java:33 }
MongoPlatformCollectionAccess.java:5 /**
MongoPlatformCollectionAccess.java:6 * Raw access, for the platform's own executors only.
MongoPlatformCollectionAccess.java:7 *
MongoPlatformCollectionAccess.java:8 * The bulk, atomic, aggregation and geospatial executors build driver-level commands and need
MongoPlatformCollectionAccess.java:9 * the unrestricted template. They are inside the platform and are the code that installs the
MongoPlatformCollectionAccess.java:10 * guardrails, which is a different position from a caller's callback — so the raw handle is a type
MongoPlatformCollectionAccess.java:11 * they ask for by name rather than something every callback receives.
MongoPlatformCollectionAccess.java:12 *
MongoPlatformCollectionAccess.java:13 * Keeping it out of {@link MongoCollectionAccess} is the point. An interface that offers both a
MongoPlatformCollectionAccess.java:14 * scoped API and an escape hatch offers an escape hatch.
MongoPlatformCollectionAccess.java:15 */
MongoPlatformCollectionAccess.java:16 public interface MongoPlatformCollectionAccess extends MongoCollectionAccess {
MongoPlatformCollectionAccess.java:17
MongoPlatformCollectionAccess.java:18 /** The template bound to the operation's consistency profile, with no collection scoping. */
MongoPlatformCollectionAccess.java:19 MongoOperations rawOperations();
MongoPlatformCollectionAccess.java:20 }
# 두 접근자를 부르는 자리 전수
저장소 전체에서 scoped() 를 부르는 줄 : 0 개
저장소 전체에서 rawOperations() 를 부르는 줄 : 7 개
두 이름이 나오는 자리 전부 (선언 포함) :
main · SpringMongoGeospatialOperations.java:58 return access.rawOperations().find(near, documentType, access.collection());
main · SpringMongoGeospatialOperations.java:82 return access.rawOperations().find(within, documentType, access.collection());
main · DefaultMongoImperativeExecutor.java:184 public ScopedMongoOperations scoped() {
main · DefaultMongoImperativeExecutor.java:192 public MongoOperations rawOperations() {
main · MongoCollectionAccess.java:32 ScopedMongoOperations scoped();
main · MongoPlatformCollectionAccess.java:19 MongoOperations rawOperations();
main · MongoAtomicOperationsTemplate.java:84 access.rawOperations(),
main · MongoAtomicOperationsTemplate.java:92 access.rawOperations(),
main · MongoBulkExecutor.java:69 access.rawOperations().bulkOps(plan.mode().toSpringMode(), access.collection());
main · DefaultReactiveMongoExecutor.java:218 public ReactiveScopedMongoOperations scoped() {
main · ReactiveMongoCollectionAccess.java:31 ReactiveScopedMongoOperations scoped();
test · MongoRawAccessBoundaryTest.java:18 * {@code MongoPlatformCollectionAccess.rawOperations()} and {@code
test · MongoRawAccessBoundaryTest.java:37 List.of(".rawOperations()", ".executeInternal(");
[대조] 그 검색이 훑은 파일 : 6444 개
# rawOperations 가 무엇을 돌려주는가
DefaultMongoImperativeExecutor.java:180 return physicalCollection;
DefaultMongoImperativeExecutor.java:181 }
DefaultMongoImperativeExecutor.java:182
DefaultMongoImperativeExecutor.java:183 @Override
DefaultMongoImperativeExecutor.java:184 public ScopedMongoOperations scoped() {
DefaultMongoImperativeExecutor.java:185 // The deadline travels with the scope. The executor can only measure elapsed time after the
DefaultMongoImperativeExecutor.java:186 // callback returns; the scoped operations send the same number to the server as maxTimeMS,
DefaultMongoImperativeExecutor.java:187 // where it actually ends the work.
DefaultMongoImperativeExecutor.java:188 return new BoundScopedOperations(physicalCollection, operations, timeout);
DefaultMongoImperativeExecutor.java:189 }
DefaultMongoImperativeExecutor.java:190
DefaultMongoImperativeExecutor.java:191 @Override
DefaultMongoImperativeExecutor.java:192 public MongoOperations rawOperations() {
DefaultMongoImperativeExecutor.java:193 return operations;
DefaultMongoImperativeExecutor.java:194 }
DefaultMongoImperativeExecutor.java:195 }
DefaultMongoImperativeExecutor.java:196 }
# 서버에 데드라인을 실제로 붙이는 다른 경로들
PolicyAwareMongoAggregationExecutor.java:88
PolicyAwareMongoAggregationExecutor.java:89 private static MongoOperationBudget budgetFor(
PolicyAwareMongoAggregationExecutor.java:90 MongoOperationContext context, MongoOperationBudget registered) {
PolicyAwareMongoAggregationExecutor.java:91 // The context's timeout is the caller's deadline; it may tighten maxTimeMS but never extend it.
PolicyAwareMongoAggregationExecutor.java:92 long contextMillis = Math.max(1L, context.timeout().toMillis());
PolicyAwareMongoAggregationExecutor.java:93 return new MongoOperationBudget(
PolicyAwareMongoAggregationExecutor.java:94 registered.maxResults(),
PolicyAwareMongoAggregationExecutor.java:95 registered.maxResultBytes(),
PolicyAwareMongoAggregationExecutor.java:96 Math.min(registered.maxTimeMillis(), contextMillis),
PolicyAwareMongoAggregationExecutor.java:97 registered.cursorBatchSize());
PolicyAwareMongoAggregationExecutor.java:98 }
PolicyAwareMongoAggregationExecutor.java:99
PolicyAwareMongoAggregationExecutor.java:100 private static AggregationOptions optionsFor(
PolicyAwareMongoAggregationExecutor.java:101 MongoAggregationProfile profile, MongoOperationBudget budget) {
PolicyAwareMongoAggregationExecutor.java:102 AggregationOptions.Builder options =
PolicyAwareMongoAggregationExecutor.java:103 AggregationOptions.builder()
PolicyAwareMongoAggregationExecutor.java:104 .allowDiskUse(profile.allowDiskUse())
PolicyAwareMongoAggregationExecutor.java:105 .cursorBatchSize(budget.cursorBatchSize())
PolicyAwareMongoAggregationExecutor.java:106 .maxTime(Duration.ofMillis(budget.maxTimeMillis()));
PolicyAwareMongoAggregationExecutor.java:107 return profile.strictMapping() ? options.strictMapping().build() : options.build();
PolicyAwareMongoAggregationExecutor.java:108 }
maxTimeMillis 를 부르는 자리 전부 (에러 메시지 포함) :
PolicyAwareMongoAggregationExecutor.java:96 Math.min(registered.maxTimeMillis(), contextMillis),
PolicyAwareMongoAggregationExecutor.java:106 .maxTime(Duration.ofMillis(budget.maxTimeMillis()));
PolicyAwareMongoQueryBuilder.java:200 query.maxTimeMsec(budget.maxTimeMillis());
MongoBudgetEnforcer.java:36 + requested.maxTimeMillis()
MongoBudgetEnforcer.java:44 + registered.maxTimeMillis()
MongoReactiveCursorPublisher.java:58 .maxTimeMsec(budget.maxTimeMillis())
context.timeout() 이나 narrowedTo 가 나오는 자리 전부 :
PolicyAwareMongoAggregationExecutor.java:72 enforcer.narrow(budget, budget.narrowedTo(budgetFor(context, budget)));
PolicyAwareMongoAggregationExecutor.java:92 long contextMillis = Math.max(1L, context.timeout().toMillis());
DefaultMongoImperativeExecutor.java:83 ScopedAccess access = new ScopedAccess(physicalCollection, operations, context.timeout());
DefaultMongoImperativeExecutor.java:93 if (elapsed.compareTo(context.timeout()) > 0) {
DefaultMongoImperativeExecutor.java:103 + context.timeout().toMillis()
MongoBudgetEnforcer.java:57 return registered.narrowedTo(requested);
MongoOperationBudget.java:43 public MongoOperationBudget narrowedTo(MongoOperationBudget other) {
DefaultReactiveMongoExecutor.java:76 .timeout(context.timeout())
DefaultReactiveMongoExecutor.java:108 .timeout(context.timeout())
DefaultReactiveMongoExecutor.java:154 context.operationName(), operationType, context.timeout()),
# 그 다섯 자리를 가진 세 실행기가 조립되는가
MongoPlatformAutoConfiguration.java:154 .MongoAtomicOperationsTemplate(executor, policies);
MongoPlatformAutoConfiguration.java:169 return new dev.caskeleton.adapter.outbound.mongo.imperative.bulk.MongoBulkExecutor(
SpringMongoGeospatialOperations.java:31 public SpringMongoGeospatialOperations(
MongoAtomicOperationsTemplate.java:27 public MongoAtomicOperationsTemplate(
MongoBulkExecutor.java:43 public MongoBulkExecutor(
그 셋이 자기 안에서 데드라인을 따로 거는가 :
SpringMongoGeospatialOperations.java maxTime 이나 timeout 이 나오는 줄 : 0 개
MongoAtomicOperationsTemplate.java maxTime 이나 timeout 이 나오는 줄 : 0 개
MongoBulkExecutor.java maxTime 이나 timeout 이 나오는 줄 : 0 개
[대조] 같은 검색을 BoundScopedOperations 에 걸면 : 8 줄
# 저장소가 그 손잡이를 어떻게 지키는가
MongoRawAccessBoundaryTest.java:15 /**
MongoRawAccessBoundaryTest.java:16 * The Mongo platform's raw escape hatches stay inside the platform.
MongoRawAccessBoundaryTest.java:17 *
MongoRawAccessBoundaryTest.java:18 * {@code MongoPlatformCollectionAccess.rawOperations()} and {@code
MongoRawAccessBoundaryTest.java:19 * DefaultMongoImperativeExecutor.executeInternal(...)} hand out Spring Data's unbounded {@code
MongoRawAccessBoundaryTest.java:20 * MongoOperations} — no collection binding, no consistency template, no deadline, no result budget.
MongoRawAccessBoundaryTest.java:21 * The scoped API exists precisely so a caller cannot reach those, and the only thing stopping one
MongoRawAccessBoundaryTest.java:22 * was a javadoc sentence saying "not public API for callers".
MongoRawAccessBoundaryTest.java:23 *
MongoRawAccessBoundaryTest.java:24 * Both are genuinely needed *inside* the platform: the geospatial, atomic and bulk operations
MongoRawAccessBoundaryTest.java:25 * are built on them. So the rule is not "delete them" but "nobody outside may call them", which is
MongoRawAccessBoundaryTest.java:26 * a boundary rather than a visibility problem — the callers live in sibling packages, so Java's
MongoRawAccessBoundaryTest.java:27 * package-private cannot express it.
MongoRawAccessBoundaryTest.java:28 *
MongoRawAccessBoundaryTest.java:29 * Checked from the composition root because that is the only place that sees both the platform
MongoRawAccessBoundaryTest.java:30 * and everything that consumes it. A rule living inside the Mongo leaf could only ever prove the
MongoRawAccessBoundaryTest.java:31 * leaf does not violate itself.
MongoRawAccessBoundaryTest.java:32 */
MongoRawAccessBoundaryTest.java:35 /** The escape hatches, by the text a caller would have to write to use one. */
MongoRawAccessBoundaryTest.java:36 private static final List