Skip to content

Commit dde52c8

Browse files
committed
feat: updated Point to be a sendable struct
Deprecated addTag(key:value:), addField(key:value:), and time(time:) in favor of using the mutable properties. BREAKING CHANGE: Point is now a value type which can cause breaking behaviour in code expecting the behaviour of a reference type. BREAKING CHANGE: addTag(key:value:), addField(key:value:), and time(time:) have mutating versions when called and the result is discarded.
1 parent 7876126 commit dde52c8

File tree

7 files changed

+439
-259
lines changed

7 files changed

+439
-259
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ Package.resolved
4444
#
4545
# Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata
4646
# hence it is not needed unless you have added a package configuration file to your project
47-
# .swiftpm
47+
.swiftpm
4848

4949
.build/
5050

CHANGELOG.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
## 1.8.0 [unreleased]
1+
## 2.0.0 [unreleased]
2+
3+
### Features
4+
1. [#69](https://github.com/influxdata/influxdb-client-swift/pull/69) and [#70](https://github.com/influxdata/influxdb-client-swift/pull/70): Updated `Point` to be a sendable struct
25

36
## 1.7.0 [2024-05-17]
47

Sources/InfluxDBSwift/InfluxDBClient.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@ extension InfluxDBClient {
247247

248248
/// An enum represents the precision for the unix timestamps within the body line-protocol.
249249
/// - SeeAlso: https://docs.influxdata.com/influxdb/latest/write-data/#timestamp-precision
250-
public enum TimestampPrecision: String, Codable, CaseIterable {
250+
public enum TimestampPrecision: String, Codable, CaseIterable, Sendable {
251251
/// Milliseconds
252252
case ms
253253
/// Seconds

Sources/InfluxDBSwift/Point.swift

Lines changed: 107 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -8,62 +8,31 @@ extension InfluxDBClient {
88
/// Point defines the values that will be written to the database.
99
///
1010
/// - SeeAlso: http://bit.ly/influxdata-point
11-
public class Point {
11+
public struct Point: Sendable {
1212
/// The measurement name.
13-
private let measurement: String
13+
public let measurement: String
1414
// The measurement tags.
15-
private var tags: [String: String?] = [:]
15+
public var tags: [String: String?]
1616
// The measurement fields.
17-
private var fields: [String: FieldValue?] = [:]
17+
public var fields: [String: FieldValue?]
1818
/// The data point time.
19-
var time: TimestampValue?
19+
public var time: TimestampValue?
2020

2121
/// Create a new Point with specified a measurement name and precision.
2222
///
2323
/// - Parameters:
2424
/// - measurement: the measurement name
2525
/// - precision: the data point precision
26-
public init(_ measurement: String) {
26+
public init(
27+
_ measurement: String,
28+
tags: [String: String?] = [:],
29+
fields: [String: FieldValue?] = [:],
30+
time: TimestampValue? = nil
31+
) {
2732
self.measurement = measurement
28-
}
29-
30-
/// Adds or replaces a tag value for this point.
31-
///
32-
/// - Parameters:
33-
/// - key: the tag name
34-
/// - value: the tag value
35-
/// - Returns: self
36-
@discardableResult
37-
public func addTag(key: String?, value: String?) -> Point {
38-
if let key = key {
39-
tags[key] = value
40-
}
41-
return self
42-
}
43-
44-
/// Adds or replaces a field value for this point.
45-
///
46-
/// - Parameters:
47-
/// - key: the field name
48-
/// - value: the field value
49-
/// - Returns: self
50-
@discardableResult
51-
public func addField(key: String?, value: FieldValue?) -> Point {
52-
if let key = key {
53-
fields[key] = value
54-
}
55-
return self
56-
}
57-
58-
/// Updates the timestamp for the point.
59-
///
60-
/// - Parameters:
61-
/// - time: the timestamp. It can be `Int` or `Date`.
62-
/// - Returns: self
63-
@discardableResult
64-
public func time(time: TimestampValue) -> Point {
33+
self.tags = tags
34+
self.fields = fields
6535
self.time = time
66-
return self
6736
}
6837

6938
/// Creates Line Protocol from Data Point.
@@ -134,7 +103,7 @@ extension InfluxDBClient {
134103

135104
extension InfluxDBClient.Point {
136105
/// Possible value types of Field
137-
public enum FieldValue {
106+
public enum FieldValue: Sendable {
138107
/// Support for Int8
139108
init(_ value: Int8) {
140109
self = .int(Int(value))
@@ -185,7 +154,7 @@ extension InfluxDBClient.Point {
185154
}
186155

187156
/// Possible value types of Field
188-
public enum TimestampValue: CustomStringConvertible {
157+
public enum TimestampValue: CustomStringConvertible, Sendable {
189158
// The number of ticks since the UNIX epoch. The value has to be specified with correct precision.
190159
case interval(Int, InfluxDBClient.TimestampPrecision = InfluxDBClient.defaultTimestampPrecision)
191160
// The date timestamp.
@@ -205,29 +174,22 @@ extension InfluxDBClient.Point {
205174
extension InfluxDBClient.Point {
206175
/// Tuple definition for construct `Point`.
207176
public typealias Tuple = (measurement: String,
208-
tags: [String?: String?]?,
209-
fields: [String?: InfluxDBClient.Point.FieldValue?],
177+
tags: [String: String?]?,
178+
fields: [String: InfluxDBClient.Point.FieldValue?],
210179
time: InfluxDBClient.Point.TimestampValue?)
211180
/// Create a new Point from Tuple.
212181
///
213182
/// - Parameters:
214183
/// - tuple: the tuple with keys: `measurement`, `tags`, `fields` and `time`
215184
/// - precision: the data point precision
216185
/// - Returns: created Point
217-
public class func fromTuple(_ tuple: Tuple) -> InfluxDBClient.Point {
218-
let point = InfluxDBClient.Point(tuple.measurement)
219-
if let tags = tuple.tags {
220-
for tag in tags {
221-
point.addTag(key: tag.0, value: tag.1)
222-
}
223-
}
224-
for field in tuple.fields {
225-
point.addField(key: field.0, value: field.1)
226-
}
227-
if let time = tuple.time {
228-
point.time(time: time)
229-
}
230-
return point
186+
public static func fromTuple(_ tuple: Tuple) -> InfluxDBClient.Point {
187+
.init(
188+
tuple.measurement,
189+
tags: tuple.tags ?? [:],
190+
fields: tuple.fields,
191+
time: tuple.time
192+
)
231193
}
232194
}
233195

@@ -386,3 +348,86 @@ extension InfluxDBClient.Point {
386348
return " \(sinceEpoch)"
387349
}
388350
}
351+
352+
extension InfluxDBClient.Point {
353+
/// Adds or replaces a tag value for this point.
354+
///
355+
/// - Parameters:
356+
/// - key: the tag name
357+
/// - value: the tag value
358+
/// - Returns: self
359+
@_disfavoredOverload
360+
@available(*, deprecated, message: "Pass tags to Point.init or use the tags property")
361+
public func addTag(key: String?, value: String?) -> Self {
362+
var point = self
363+
if let key = key {
364+
point.tags[key] = value
365+
}
366+
return point
367+
}
368+
369+
/// Adds or replaces a tag value for this point.
370+
///
371+
/// - Parameters:
372+
/// - key: the tag name
373+
/// - value: the tag value
374+
/// - Returns: self
375+
@available(*, deprecated, message: "Pass tags to Point.init or use the tags property")
376+
public mutating func addTag(key: String?, value: String?) {
377+
if let key = key {
378+
tags[key] = value
379+
}
380+
}
381+
382+
/// Adds or replaces a field value for this point.
383+
///
384+
/// - Parameters:
385+
/// - key: the field name
386+
/// - value: the field value
387+
/// - Returns: self
388+
@_disfavoredOverload
389+
@available(*, deprecated, message: "Pass fields to Point.init or use the fields property")
390+
public func addField(key: String?, value: FieldValue?) -> Self {
391+
var point = self
392+
if let key = key {
393+
point.fields[key] = value
394+
}
395+
return point
396+
}
397+
398+
/// Adds or replaces a field value for this point.
399+
///
400+
/// - Parameters:
401+
/// - key: the field name
402+
/// - value: the field value
403+
/// - Returns: self
404+
@available(*, deprecated, message: "Pass fields to Point.init or use the fields property")
405+
public mutating func addField(key: String?, value: FieldValue?) {
406+
if let key = key {
407+
fields[key] = value
408+
}
409+
}
410+
411+
/// Updates the timestamp for the point.
412+
///
413+
/// - Parameters:
414+
/// - time: the timestamp. It can be `Int` or `Date`.
415+
/// - Returns: self
416+
@_disfavoredOverload
417+
@available(*, deprecated, message: "Pass time to Point.init or use the time property")
418+
public func time(time: TimestampValue) -> Self {
419+
var point = self
420+
point.time = time
421+
return point
422+
}
423+
424+
/// Updates the timestamp for the point.
425+
///
426+
/// - Parameters:
427+
/// - time: the timestamp. It can be `Int` or `Date`.
428+
/// - Returns: self
429+
@available(*, deprecated, message: "Pass time to Point.init or use the time property")
430+
public mutating func time(time: TimestampValue) {
431+
self.time = time
432+
}
433+
}

Tests/InfluxDBSwiftTests/IntegrationTests.swift

Lines changed: 38 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,15 @@ final class IntegrationTests: XCTestCase {
3838
let measurement = "h2o_\(Date().timeIntervalSince1970)"
3939

4040
let points = Array(1...5).map {
41-
InfluxDBClient.Point(measurement)
42-
.addTag(key: "host", value: "aws")
43-
.addTag(key: "location", value: "west")
44-
.addField(key: "value", value: .int($0))
45-
.time(time: .date(Date(2020, 7, $0)))
41+
InfluxDBClient.Point(
42+
measurement,
43+
tags: [
44+
"host": "aws",
45+
"location": "west"
46+
],
47+
fields: ["value": .int($0)],
48+
time: .date(Date(2020, 7, $0))
49+
)
4650
}
4751

4852
client.makeWriteAPI().write(points: points) { _, error in
@@ -92,23 +96,35 @@ final class IntegrationTests: XCTestCase {
9296

9397
let measurement = "h2o_\(Date().timeIntervalSince1970)"
9498

95-
let point1 = InfluxDBClient.Point(measurement)
96-
.addTag(key: "host", value: "aws")
97-
.addTag(key: "location", value: "west")
98-
.addField(key: "value", value: .int(1))
99-
.time(time: .date(Date(2020, 7, 1)))
100-
101-
let point2 = InfluxDBClient.Point(measurement)
102-
.addTag(key: "host", value: "azure")
103-
.addTag(key: "location", value: "west")
104-
.addField(key: "value", value: .int(2))
105-
.time(time: .date(Date(2020, 7, 2)))
106-
107-
let point3 = InfluxDBClient.Point(measurement)
108-
.addTag(key: "host", value: "gc")
109-
.addTag(key: "location", value: "west")
110-
.addField(key: "value", value: .int(3))
111-
.time(time: .date(Date(2020, 7, 3)))
99+
let point1 = InfluxDBClient.Point(
100+
measurement,
101+
tags: [
102+
"host": "aws",
103+
"location": "west"
104+
],
105+
fields: ["value": .int(1)],
106+
time: .date(Date(2020, 7, 1))
107+
)
108+
109+
let point2 = InfluxDBClient.Point(
110+
measurement,
111+
tags: [
112+
"host": "azure",
113+
"location": "west"
114+
],
115+
fields: ["value": .int(2)],
116+
time: .date(Date(2020, 7, 2))
117+
)
118+
119+
let point3 = InfluxDBClient.Point(
120+
measurement,
121+
tags: [
122+
"host": "gc",
123+
"location": "west"
124+
],
125+
fields: ["value": .int(3)],
126+
time: .date(Date(2020, 7, 3))
127+
)
112128

113129
client.makeWriteAPI().write(points: [point1, point2, point3]) { _, error in
114130
if let error = error {

0 commit comments

Comments
 (0)