diff options
author | Dan Larkin-York <dan.larkin-york@mongodb.com> | 2021-07-06 20:29:04 +0000 |
---|---|---|
committer | Dan Larkin-York <dan.larkin-york@mongodb.com> | 2021-07-14 16:01:26 +0000 |
commit | 3b9982be740bc360691f46ed534427065763c16f (patch) | |
tree | ac06cd2626aac50f2658cb85b47328c098130eb3 /src/mongo/db/commands/dbcommands.cpp | |
parent | 3e8b8bbf8fd4243d9b7e81fbb569d492da05628a (diff) | |
download | mongo-3b9982be740bc360691f46ed534427065763c16f.tar.gz |
SERVER-58171 Changing time-series granularity does not update view definition
Diffstat (limited to 'src/mongo/db/commands/dbcommands.cpp')
-rw-r--r-- | src/mongo/db/commands/dbcommands.cpp | 70 |
1 files changed, 62 insertions, 8 deletions
diff --git a/src/mongo/db/commands/dbcommands.cpp b/src/mongo/db/commands/dbcommands.cpp index 888ead550e0..7293ed47275 100644 --- a/src/mongo/db/commands/dbcommands.cpp +++ b/src/mongo/db/commands/dbcommands.cpp @@ -110,8 +110,8 @@ namespace { * Returns a CollMod on the underlying buckets collection of the time-series collection. * Returns null if 'origCmd' is not for a time-series collection. */ -std::unique_ptr<CollMod> makeTimeseriesCollModCommand(OperationContext* opCtx, - const CollMod& origCmd) { +std::unique_ptr<CollMod> makeTimeseriesBucketsCollModCommand(OperationContext* opCtx, + const CollMod& origCmd) { const auto& origNs = origCmd.getNamespace(); auto timeseriesOptions = timeseries::getTimeseriesOptions(opCtx, origNs); @@ -149,6 +149,43 @@ std::unique_ptr<CollMod> makeTimeseriesCollModCommand(OperationContext* opCtx, return cmd; } +/** + * Returns a CollMod on the view definition of the time-series collection. + * Returns null if 'origCmd' is not for a time-series collection or if the view definition need not + * be changed. + */ +std::unique_ptr<CollMod> makeTimeseriesViewCollModCommand(OperationContext* opCtx, + const CollMod& origCmd) { + const auto& ns = origCmd.getNamespace(); + + auto timeseriesOptions = timeseries::getTimeseriesOptions(opCtx, ns); + + // Return early with null if we are not working with a time-series collection. + if (!timeseriesOptions) { + return {}; + } + + auto& tsMod = origCmd.getTimeseries(); + if (tsMod) { + auto res = + timeseries::applyTimeseriesOptionsModifications(*timeseriesOptions, tsMod->toBSON()); + if (res.isOK()) { + auto& [newOptions, changed] = res.getValue(); + if (changed) { + auto cmd = std::make_unique<CollMod>(ns); + constexpr bool asArray = false; + std::vector<BSONObj> pipeline = { + timeseries::generateViewPipeline(newOptions, asArray)}; + cmd->setPipeline(std::move(pipeline)); + return cmd; + } + } + } + + return {}; +} + + class CmdDropDatabase : public DropDatabaseCmdVersion1Gen<CmdDropDatabase> { public: std::string help() const final { @@ -579,12 +616,29 @@ public: // time-series collection, which are important for maintaining the view-bucket // relationship. // - // 'timeseriesCmd' is null if the request namespace does not refer to a time-series - // collection. Otherwise, transforms the user time-series index request to one on the - // underlying bucket. - auto timeseriesCmd = makeTimeseriesCollModCommand(opCtx, requestParser.request()); - if (timeseriesCmd) { - cmd = timeseriesCmd.get(); + // 'timeseriesBucketsCmd' is null if the request namespace does not refer to a time-series + // collection. Otherwise, transforms the user time-series collMod request to one on the + // underlying bucket collection. + auto timeseriesBucketsCmd = + makeTimeseriesBucketsCollModCommand(opCtx, requestParser.request()); + if (timeseriesBucketsCmd) { + // We additionally create a special, limited collMod command for the view definition + // itself if the pipeline needs to be updated to reflect changed timeseries options. + // This operation is completed first. In the case that we get a partial update where + // only one of the two collMod operations fully completes (e.g. replication rollback), + // having the view pipeline update without updating the timeseries options on the + // buckets collection will result in sub-optimal performance, but correct behavior. + // If the timeseries options were updated without updating the view pipeline, we could + // end up with incorrect query behavior (namely data missing from some queries). + auto timeseriesViewCmd = + makeTimeseriesViewCollModCommand(opCtx, requestParser.request()); + if (timeseriesViewCmd) { + uassertStatusOK(collMod(opCtx, + timeseriesViewCmd->getNamespace(), + timeseriesViewCmd->toBSON(BSONObj()), + &result)); + } + cmd = timeseriesBucketsCmd.get(); } uassertStatusOK(collMod(opCtx, cmd->getNamespace(), cmd->toBSON(BSONObj()), &result)); |