Skip to content

Commit b56d7d6

Browse files
SWIFT-1108 Add options for time series collections (#681)
1 parent eda470e commit b56d7d6

File tree

9 files changed

+472
-5
lines changed

9 files changed

+472
-5
lines changed

Sources/MongoSwift/Operations/CreateCollectionOperation.swift

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ public struct CreateCollectionOptions: Codable, CodingStrategyProvider {
2121
/// decoded using this strategy.
2222
public var dateCodingStrategy: DateCodingStrategy? = nil
2323

24+
/// Number of seconds after which old time series data should be deleted.
25+
public var expireAfterSeconds: Int?
26+
2427
/// Specify a default configuration for indexes created on this collection.
2528
public var indexOptionDefaults: BSONDocument?
2629

@@ -37,6 +40,9 @@ public struct CreateCollectionOptions: Codable, CodingStrategyProvider {
3740
/// Specifies storage engine configuration for this collection.
3841
public var storageEngine: BSONDocument?
3942

43+
/// The options used for creating a time series collection. This feature is only available on MongoDB 5.0+.
44+
public var timeseries: TimeseriesOptions?
45+
4046
/// Specifies the `UUIDCodingStrategy` to use for BSON encoding/decoding operations performed by this collection.
4147
/// It is the responsibility of the user to ensure that any `UUID`s already stored in this collection can be
4248
/// decoded using this strategy.
@@ -63,7 +69,7 @@ public struct CreateCollectionOptions: Codable, CodingStrategyProvider {
6369

6470
private enum CodingKeys: String, CodingKey {
6571
case capped, size, max, storageEngine, validator, validationLevel, validationAction,
66-
indexOptionDefaults, viewOn, pipeline, collation, writeConcern
72+
indexOptionDefaults, viewOn, pipeline, collation, writeConcern, timeseries, expireAfterSeconds
6773
}
6874

6975
/// Convenience initializer allowing any/all parameters to be omitted or optional.
@@ -72,11 +78,13 @@ public struct CreateCollectionOptions: Codable, CodingStrategyProvider {
7278
collation: BSONDocument? = nil,
7379
dataCodingStrategy: DataCodingStrategy? = nil,
7480
dateCodingStrategy: DateCodingStrategy? = nil,
81+
expireAfterSeconds: Int? = nil,
7582
indexOptionDefaults: BSONDocument? = nil,
7683
max: Int? = nil,
7784
pipeline: [BSONDocument]? = nil,
7885
size: Int? = nil,
7986
storageEngine: BSONDocument? = nil,
87+
timeseries: TimeseriesOptions? = nil,
8088
uuidCodingStrategy: UUIDCodingStrategy? = nil,
8189
validationAction: String? = nil,
8290
validationLevel: String? = nil,
@@ -99,6 +107,45 @@ public struct CreateCollectionOptions: Codable, CodingStrategyProvider {
99107
self.validator = validator
100108
self.viewOn = viewOn
101109
self.writeConcern = writeConcern
110+
self.timeseries = timeseries
111+
self.expireAfterSeconds = expireAfterSeconds
112+
}
113+
}
114+
115+
/// The options to use when creating a time series collection.
116+
public struct TimeseriesOptions: Codable {
117+
/// Name of the top-level field to be used for time. Inserted documents must have this field, and the field must
118+
/// be of the BSON UTC datetime type.
119+
public var timeField: String
120+
121+
/// Name of the top-level field describing the series. This field is used to group related data and may be of any
122+
/// BSON type except array. This name must not be the same as the `timeField` or `_id`.
123+
public var metaField: String?
124+
125+
/// The units used to describe the expected interval between subsequent measurements for a time series
126+
/// collection. Defaults to `Granularity.seconds` if unset.
127+
public var granularity: Granularity?
128+
129+
/// The units used to describe the expected interval between subsequent measurements for a time series collection.
130+
public struct Granularity: RawRepresentable, Codable {
131+
public static let seconds = Granularity("seconds")
132+
public static let minutes = Granularity("minutes")
133+
public static let hours = Granularity("hours")
134+
135+
/// For an unknown value. For forwards compatibility, no error will be thrown when an unknown value is
136+
/// provided.
137+
public static func other(_ value: String) -> Granularity {
138+
Granularity(value)
139+
}
140+
141+
public var rawValue: String
142+
143+
public init?(rawValue: String) { self.rawValue = rawValue }
144+
internal init(_ value: String) { self.rawValue = value }
145+
}
146+
147+
private enum CodingKeys: String, CodingKey {
148+
case timeField, metaField, granularity
102149
}
103150
}
104151

Sources/MongoSwiftSync/Exports.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Generated using Sourcery 1.3.4 — https://github.com/krzysztofzablocki/Sourcery
1+
// Generated using Sourcery 1.6.0 — https://github.com/krzysztofzablocki/Sourcery
22
// DO NOT EDIT
33

44
// Re-export the BSON library
@@ -76,6 +76,7 @@
7676
@_exported import struct MongoSwift.ServerHeartbeatStartedEvent
7777
@_exported import struct MongoSwift.ServerHeartbeatSucceededEvent
7878
@_exported import struct MongoSwift.ServerOpeningEvent
79+
@_exported import struct MongoSwift.TimeseriesOptions
7980
@_exported import struct MongoSwift.TopologyClosedEvent
8081
@_exported import struct MongoSwift.TopologyDescription
8182
@_exported import struct MongoSwift.TopologyDescriptionChangedEvent

Tests/LinuxMain.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Generated using Sourcery 1.3.4 — https://github.com/krzysztofzablocki/Sourcery
1+
// Generated using Sourcery 1.6.0 — https://github.com/krzysztofzablocki/Sourcery
22
// DO NOT EDIT
33

44
@testable import BSONTests
@@ -234,6 +234,7 @@ extension MongoDatabaseTests {
234234
("testMongoDatabase", testMongoDatabase),
235235
("testDropDatabase", testDropDatabase),
236236
("testCreateCollection", testCreateCollection),
237+
("testCreateCollectionUnified", testCreateCollectionUnified),
237238
("testListCollections", testListCollections),
238239
("testListCollectionsBatchSize", testListCollectionsBatchSize),
239240
("testAggregate", testAggregate),

Tests/MongoSwiftSyncTests/MongoDatabaseTests.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,16 @@ final class MongoDatabaseTests: MongoSwiftTestCase {
138138
expect(collectionInfo[1]).to(equal(expectedView))
139139
}
140140

141+
func testCreateCollectionUnified() throws {
142+
let tests = try retrieveSpecTestFiles(
143+
specName: "collection-management",
144+
asType: UnifiedTestFile.self
145+
).map { $0.1 }
146+
147+
let runner = try UnifiedTestRunner()
148+
try runner.runFiles(tests)
149+
}
150+
141151
func testListCollections() throws {
142152
let client = try MongoClient.makeTestClient()
143153
let monitor = client.addCommandMonitor()

Tests/MongoSwiftSyncTests/UnifiedTestRunner/HasListableProperties.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,4 @@ extension UpdateOptions: HasListableProperties {}
2424
extension ReplaceOneModelOptions: HasListableProperties {}
2525
extension ChangeStreamOptions: HasListableProperties {}
2626
extension ListCollectionsOptions: HasListableProperties {}
27+
extension CreateCollectionOptions: HasListableProperties {}

Tests/MongoSwiftSyncTests/UnifiedTestRunner/UnifiedDatabaseOperations.swift

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,30 @@ struct UnifiedCreateCollection: UnifiedOperationProtocol {
77
/// Optional identifier for a session entity to use.
88
let session: String?
99

10+
let options: CreateCollectionOptions
11+
12+
enum CodingKeys: String, CodingKey, CaseIterable {
13+
case collection, session
14+
}
15+
16+
init(from decoder: Decoder) throws {
17+
self.options = try decoder.singleValueContainer().decode(CreateCollectionOptions.self)
18+
let container = try decoder.container(keyedBy: CodingKeys.self)
19+
self.collection = try container.decode(String.self, forKey: .collection)
20+
self.session = try container.decodeIfPresent(String.self, forKey: .session)
21+
}
22+
1023
static var knownArguments: Set<String> {
11-
["collection", "session"]
24+
Set(
25+
CodingKeys.allCases.map { $0.rawValue } +
26+
CreateCollectionOptions().propertyNames
27+
)
1228
}
1329

1430
func execute(on object: UnifiedOperation.Object, context: Context) throws -> UnifiedOperationResult {
1531
let db = try context.entities.getEntity(from: object).asDatabase()
1632
let session = try context.entities.resolveSession(id: self.session)
17-
_ = try db.createCollection(self.collection, session: session)
33+
_ = try db.createCollection(self.collection, options: self.options, session: session)
1834
return .none
1935
}
2036
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
===========================
2+
Collection Management Tests
3+
===========================
4+
5+
This directory contains tests for collection management. They are implemented
6+
in the `Unified Test Format <../../unified-test-format/unified-test-format.rst>`__
7+
and require schema version 1.0.

0 commit comments

Comments
 (0)