Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,31 @@ const bucketsColl = db.getCollection('system.buckets.' + collName);
// be used for storing the measurements of the buckets with mismatched embedded
// bucket id timestamp and control.min timestamp.
// ------------------------------------------------------------------------------------
listCollectionsRes = db.runCommand({

//
// Helper function to validate namespaces, create temporary collection and
// return our timeseries options.
//
function verifyAndSetupCollsAndGetTSOptions(collName, tempColl) {
tsOptions = db.runCommand({listCollections : 1.0, filter : {name : collName}})
.cursor.firstBatch[0]
.options.timeseries;

if (tsOptions === undefined) {
print('Collection "' + collName + '" is not a timeseries collection.');
exit(1);
}
listCollectionsRes = db.runCommand({
listCollections: 1.0,
filter: {name: 'temp'}
filter: {name: tempColl}
}).cursor.firstBatch;
if (listCollectionsRes.length != 0) {
print(
'Collection `temp` should not exist prior to running the script. Rename or drop the collection before running this script');
exit(1);
if (listCollectionsRes.length != 0) {
print(
'Collection ' + tempColl + ' should not exist prior to running the script. Rename or drop the collection before running this script');
exit(1);
}
db.createCollection(tempColl, {timeseries : tsOptions});
return tsOptions;
}

// ---------------------------------------------------------------------------------------
Expand Down Expand Up @@ -59,20 +76,14 @@ let bucketColl;
let tsOptions;
let tempTimeseriesColl;
let tempTimeseriesBucketsColl;
let tempTimeseriesCollName = 'temp';

function setUp() {
bucketColl = db.getCollection('system.buckets.' + collName);
tsOptions = verifyAndSetupCollsAndGetTSOptions(collName, tempColl);

// Create a temp collection to store measurements from the buckets with
// mismatched embedded bucket id timestamp and control.min timestamp.
tsOptions =
db.runCommand({listCollections: 1.0, filter: {name: coll.getName()}})
.cursor.firstBatch[0]
.options.timeseries;

db.createCollection('temp', {timeseries: tsOptions});
tempTimeseriesColl = db.getCollection('temp');
tempTimeseriesBucketsColl = db.getCollection('system.buckets.temp');
tempTimeseriesColl = db.getCollection(tempTimeseriesCollName);
tempTimeseriesBucketsColl = db.getCollection('system.buckets.' + tempTimeseriesCollName);
}

// Helper function to determine if timestamp is in extended range.
Expand Down
54 changes: 18 additions & 36 deletions sharded-timeseries-orphan-check/check_ts_coll_orphans.js
Original file line number Diff line number Diff line change
Expand Up @@ -325,43 +325,11 @@ function stageOrphanedTimeSeriesDocumentsForRecovery(orphanedDocsResults, namesp
return
}

// Also - verify that it is time series
// Any record in the results collection _should_ already be verified as time-series - but let's be extra cautious
existing_coll_info = getCollectionInfosFromNamespace(staging_ns)
if(existing_coll_info.length > 0) {
if(!existing_coll_info[0].options.timeseries) {
log('ERROR', `Existing namespace ${namespace} already exists but is not a time series collection`)
return
}
}

// 3.0 Check that the staging collection, if it exists, has the same time series option as the original collection
results = getCollectionInfosFromNamespace(staging_ns)

// If collection exists - collection must be time series and have same options as the original namespace
if(results.length > 0) {
staging_ts_options = results[0].options.timeseries
existing_ts_options = getCollectionInfosFromNamespace(existing_ns)[0].options.timeseries

// One or both of existing and staging collections are not time series
if(!staging_ts_options) {
log('ERROR', `Staging namespace ${staging_namespace} already exists but is not a time series collection`)
return
}

// Options on staging don't match options on existing collection
if(JSON.stringify(staging_ts_options) != JSON.stringify(existing_ts_options)) {
log('ERROR', `Staging namespace does not have the same collection options as the existing namespace - staging options: ${JSON.stringify(staging_ts_options)}, existing: ${JSON.stringify(existing_ts_options)}`)
return
}
}
// 3. Check that the existing collection is a time series collection, throw if the staging_ns collection already exists,
// and create the unsharded staging collection with the same timeseries options as the original collection.
verifyAndSetupCollsAndGetTSOptions(existing_ns, staging_ns);

// 3.1 - Create the unsharded staging collection with the same timeseries options as the original collection
// We only grab ts_options in the event that any other setting may be defined
ts_options = getCollectionInfosFromNamespace(existing_ns)[0].options.timeseries
db.getSiblingDB(staging_ns.dbname).createCollection(staging_ns.collname, { "timeseries": ts_options })

// 4.0 - Move orphaned bucket documents from each shard into the staging bucket collections
// 4. - Move orphaned bucket documents from each shard into the staging bucket collections
print(`Moving bucket documents to staging collection...\n`);
let shardConns = getConnectionsToShards();
var cur = db.getCollection(orphanedDocsResults).find({ "orphanDocData.parentNamespace": existing_ns.dbname + ".system.buckets." + existing_ns.collname })
Expand Down Expand Up @@ -449,6 +417,20 @@ function getCollectionInfosFromNamespace(namespace_ns) {
return db.getSiblingDB(namespace_ns.dbname).getCollectionInfos({ "name": namespace_ns.collname })
}

function verifyAndSetupCollsAndGetTSOptions(existing_ns, staging_ns) {
existing_coll_info = getCollectionInfosFromNamespace(existing_ns);
ts_options = existing_coll_info[0].options.timeseries;

if(!existing_ts_options) {
throw new Error(`Existing namespace: ${existing_ns} is not a time series collections.`);
}
staging_coll_info = getCollectionInfosFromNamespace(staging_ns);
if(staging_coll_info.length > 0) {
throw new Error(`Staging namespace: ${namespace} already exists. Please re-run with a different staging_ns or drop the staging_ns coll.`)
}
db.getSiblingDB(staging_ns.dbname).createCollection(staging_ns.collname, { "timeseries": ts_options })
}

// Parse a db.collection namespace into names, taking into account that a collection name can contain periods.
function parseNamespace(namespace) {
names_split = namespace.split(".")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,26 +14,18 @@ function verifyAndSetupCollsAndGetTSOptions(collName, tempColl) {
.options.timeseries;

if (tsOptions === undefined) {
throw ('Collection "' + collName + '" is not a timeseries collection.');
print('Collection "' + collName + '" is not a timeseries collection.');
exit(1);
}

// Verify that if the temp collection has the same options if it exists
tempRes = db.runCommand({listCollections : 1.0, filter : {name : tempColl}})
.cursor.firstBatch;
if (tempRes && tempRes.length > 0) {
tempOptions = tempRes[0].options.timeseries;
if (tempOptions === undefined ||
tsOptions.timeField != tempOptions.timeField ||
tsOptions.metaField != tempOptions.metaField ||
tsOptions.granularity != tempOptions.granularity ||
tsOptions.bucketMaxSpanSeconds != tempOptions.bucketMaxSpanSeconds) {
throw (
'Temp collection "' + tempColl +
'" exists but contain unexpected options. Please specify a different temporary namespace.');
}
db.getCollection(tempColl).drop();
listCollectionsRes = db.runCommand({
listCollections: 1.0,
filter: {name: tempColl}
}).cursor.firstBatch;
if (listCollectionsRes.length != 0) {
print(
'Collection ' + tempColl + ' should not exist prior to running the script. Rename or drop the collection before running this script');
exit(1);
}

db.createCollection(tempColl, {timeseries : tsOptions});
return tsOptions;
}
Expand Down
28 changes: 10 additions & 18 deletions timeseries-bucket-repair/timeseries_bucket_repair.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,26 +14,18 @@ function verifyAndSetupCollsAndGetTSOptions(collName, tempColl) {
.options.timeseries;

if (tsOptions === undefined) {
throw ('Collection "' + collName + '" is not a timeseries collection.');
print('Collection "' + collName + '" is not a timeseries collection.');
exit(1);
}

// Verify that the temp collection has the same options if it exists
tempRes = db.runCommand({listCollections : 1.0, filter : {name : tempColl}})
.cursor.firstBatch;
if (tempRes && tempRes.length > 0) {
tempOptions = tempRes[0].options.timeseries;
if (tempOptions === undefined ||
tsOptions.timeField != tempOptions.timeField ||
tsOptions.metaField != tempOptions.metaField ||
tsOptions.granularity != tempOptions.granularity ||
tsOptions.bucketMaxSpanSeconds != tempOptions.bucketMaxSpanSeconds) {
throw (
'Temp collection "' + tempColl +
'" exists but contain unexpected options. Please specify a different temporary namespace.');
}
db.getCollection(tempColl).drop();
listCollectionsRes = db.runCommand({
listCollections: 1.0,
filter: {name: tempColl}
}).cursor.firstBatch;
if (listCollectionsRes.length != 0) {
print(
'Collection ' + tempColl + ' should not exist prior to running the script. Rename or drop the collection before running this script');
exit(1);
}

db.createCollection(tempColl, {timeseries : tsOptions});
return tsOptions;
}
Expand Down
37 changes: 28 additions & 9 deletions timeseries-mixed-schema/rewrite_timeseries_mixed_schema_buckets.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,31 @@ const bucketsColl = db.getCollection('system.buckets.' + collName);
// The "temp" collection should not exist prior to running the script. This will be used
// for storing the measurements of the mixed-schema buckets.
// ------------------------------------------------------------------------------------
listCollectionsRes = db.runCommand({ listCollections: 1.0, filter: { name: "temp" } }).cursor.firstBatch;
if (listCollectionsRes.length != 0) {
print("Collection `temp` should not exist prior to running the script. Rename or drop the collection before running this script");

//
// Helper function to validate namespaces, create temporary collection and
// return our timeseries options.
//
function verifyAndSetupCollsAndGetTSOptions(collName, tempColl) {
tsOptions = db.runCommand({listCollections : 1.0, filter : {name : collName}})
.cursor.firstBatch[0]
.options.timeseries;

if (tsOptions === undefined) {
print('Collection "' + collName + '" is not a timeseries collection.');
exit(1);
}
listCollectionsRes = db.runCommand({
listCollections: 1.0,
filter: {name: tempColl}
}).cursor.firstBatch;
if (listCollectionsRes.length != 0) {
print(
'Collection ' + tempColl + ' should not exist prior to running the script. Rename or drop the collection before running this script');
exit(1);
}
db.createCollection(tempColl, {timeseries : tsOptions});
return tsOptions;
}

// ---------------------------------------------------------------------------------------
Expand All @@ -38,18 +59,16 @@ let bucketColl;
let tsOptions;
let tempTimeseriesColl;
let tempTimeseriesBucketsColl;
let tempTimeseriesCollName = 'temp';

function setUp() {
bucketColl = db.getCollection("system.buckets." + collName);

// Create a temp collection to store measurements from the mixed-schema buckets.
tsOptions = db.runCommand({ listCollections: 1.0, filter: { name: coll.getName() } })
.cursor.firstBatch[0]
.options.timeseries;
tsOptions = verifyAndSetupCollsAndGetTSOptions(coll.getName(), tempTimeseriesCollName)

db.createCollection("temp", { timeseries: tsOptions });
tempTimeseriesColl = db.getCollection("temp");
tempTimeseriesBucketsColl = db.getCollection("system.buckets.temp");
tempTimeseriesColl = db.getCollection(tempTimeseriesCollName);
tempTimeseriesBucketsColl = db.getCollection("system.buckets." + tempTimeseriesCollName);
}

function runMixedSchemaBucketsReinsertionProcedure() {
Expand Down