summaryrefslogtreecommitdiff
path: root/jstests/sharding/timeseries_shard_collection.js
blob: dd36e353701abf533f5e16bc53d49089b1368899 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
/**
 * Tests that time-series collections can be sharded with different configurations.
 *
 * @tags: [
 *   disabled_due_to_server_58295
 * ]
 */

(function() {
load("jstests/core/timeseries/libs/timeseries.js");

Random.setRandomSeed();

const st = new ShardingTest({shards: 2, rs: {nodes: 2}});

const dbName = 'test';
const sDB = st.s.getDB(dbName);

if (!TimeseriesTest.timeseriesCollectionsEnabled(st.shard0)) {
    jsTestLog("Skipping test because the time-series collection feature flag is disabled");
    st.stop();
    return;
}

if (TimeseriesTest.shardedtimeseriesCollectionsEnabled(st.shard0)) {
    function validateBucketsCollectionSharded({collName, shardKey, timeSeriesParams}) {
        const configColls = st.s.getDB('config').collections;
        const output = configColls
                           .find({
                               _id: 'test.system.buckets.' + collName,
                               key: shardKey,
                               timeseriesFields: {$exists: true}
                           })
                           .toArray();
        assert.eq(output.length, 1, configColls.find().toArray());
        assert.eq(output[0].timeseriesFields.timeField, timeSeriesParams.timeField, output[0]);
        assert.eq(output[0].timeseriesFields.metaField, timeSeriesParams.metaField, output[0]);
    }

    // Simple shard key on the metadata field.
    (function metaShardKey() {
        assert.commandWorked(
            sDB.createCollection('ts', {timeseries: {timeField: 'time', metaField: 'hostId'}}));

        assert.commandWorked(st.s.adminCommand({enableSharding: 'test'}));

        // This index gets created as {meta: 1} on the buckets collection.
        assert.commandWorked(sDB.ts.createIndex({hostId: 1}));

        // Command should fail since the 'timeseries' specification does not match that existing
        // collection.
        assert.commandFailedWithCode(
            st.s.adminCommand(
                {shardCollection: 'test.ts', key: {'hostId': 1}, timeseries: {timeField: 'time'}}),
            5731500);

        assert.commandWorked(st.s.adminCommand({
            shardCollection: 'test.ts',
            key: {'hostId': 1},
            timeseries: {timeField: 'time', metaField: 'hostId'}
        }));

        validateBucketsCollectionSharded({
            collName: 'ts',
            shardKey: {meta: 1},
            timeSeriesParams: {timeField: 'time', metaField: 'hostId'}
        });

        assert.commandWorked(
            st.s.adminCommand({split: 'test.system.buckets.ts', middle: {meta: 10}}));

        const primaryShard = st.getPrimaryShard(dbName);
        assert.commandWorked(st.s.adminCommand({
            movechunk: 'test.system.buckets.ts',
            find: {meta: 10},
            to: st.getOther(primaryShard).shardName,
            _waitForDelete: true
        }));

        let counts = st.chunkCounts('system.buckets.ts', 'test');
        assert.eq(1, counts[st.shard0.shardName]);
        assert.eq(1, counts[st.shard1.shardName]);

        sDB.dropDatabase();
    })();

    // Shard key on the metadata field and time fields.
    function metaAndTimeShardKey() {
        assert.commandWorked(st.s.adminCommand({enableSharding: 'test'}));
        assert.commandWorked(st.s.adminCommand({
            shardCollection: 'test.ts',
            key: {'hostId': 1, 'time': 1},
            timeseries: {timeField: 'time', metaField: 'hostId'},
        }));

        validateBucketsCollectionSharded({
            collName: 'ts',
            // The 'time' field should be translated to 'control.min.time' on buckets collection.
            shardKey: {meta: 1, 'control.min.time': 1},
            timeSeriesParams: {timeField: 'time', metaField: 'hostId'}
        });

        assert.commandWorked(st.s.adminCommand(
            {split: 'test.system.buckets.ts', middle: {meta: 10, 'control.min.time': MinKey}}));

        const primaryShard = st.getPrimaryShard(dbName);
        assert.commandWorked(st.s.adminCommand({
            movechunk: 'test.system.buckets.ts',
            find: {meta: 10, 'control.min.time': MinKey},
            to: st.getOther(primaryShard).shardName,
            _waitForDelete: true
        }));

        let counts = st.chunkCounts('system.buckets.ts', 'test');
        assert.eq(1, counts[st.shard0.shardName]);
        assert.eq(1, counts[st.shard1.shardName]);

        sDB.dropDatabase();
    }

    // Sharding a collection with an existing timeseries collection.
    assert.commandWorked(
        sDB.createCollection('ts', {timeseries: {timeField: 'time', metaField: 'hostId'}}));
    metaAndTimeShardKey();

    // Sharding a collection with a new timeseries collection.
    metaAndTimeShardKey();

} else {
    (function timeseriesCollectionsCannotBeSharded() {
        assert.commandWorked(st.s.adminCommand({enableSharding: dbName}));

        assert.commandFailedWithCode(st.s.adminCommand({
            shardCollection: 'test.ts',
            key: {meta: 1},
            timeseries: {timeField: 'time', metaField: 'hostId'}
        }),
                                     5731502);

        assert.commandWorked(
            sDB.createCollection('ts', {timeseries: {timeField: 'time', metaField: 'hostId'}}));

        assert.commandFailedWithCode(
            st.s.adminCommand({shardCollection: 'test.ts', key: {meta: 1}}), 5731502);

        // Insert directly on the primary shard because mongos does not know how to insert into a TS
        // collection.
        st.ensurePrimaryShard(dbName, st.shard0.shardName);
        const tsColl = st.shard0.getDB(dbName).ts;
        const numDocs = 20;
        let docs = [];
        for (let i = 0; i < numDocs; i++) {
            const doc = {
                time: ISODate(),
                hostId: i,
                _id: i,
                data: Random.rand(),
            };
            docs.push(doc);
            assert.commandWorked(tsColl.insert(doc));
        }

        // This index gets created as {meta: 1} on the buckets collection.
        assert.commandWorked(tsColl.createIndex({hostId: 1}));

        // Trying to shard the buckets collection -> error
        assert.commandFailedWithCode(
            st.s.adminCommand({shardCollection: 'test.system.buckets.ts', key: {meta: 1}}),
            5731501);

        assert.commandWorked(sDB.dropDatabase());
    })();
}

st.stop();
})();