Skip to content

feat: updated Point to be a sendable struct #71

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
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
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ Package.resolved
#
# Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata
# hence it is not needed unless you have added a package configuration file to your project
# .swiftpm
.swiftpm

.build/

Expand Down
12 changes: 11 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,14 @@
## 1.8.0 [unreleased]
## 2.0.0 [unreleased]

`Point` has been updated from a class to a `Sendable` struct. This allows passing instances of `Point` across arbitrary concurrent contexts without introducing a risk of data races. Anywhere using `Point` will need to be updated to account for the change from a class to a struct.

The minimum swift version has been raised to 5.7 to support the `Sendable` protocol.

`addTag(key:value:)`, `addField(key:value:)`, and `time(time:)` have been deprecated in favor of passing values to `Point.init` or mutating the properties directly. Since the methods mutated the instance and returned the instance, they aren't compatible with `Point` becoming a struct. To simplify migration, each method now has two versions: one that mutates the instance and one that returns a new modified instance. The methods returning a new instance can still be chained together but the result must be assigned to a variable. The methods that mutate the instance can no longer be chained together, but don't require assigning the result to a variable.

### Features
1. [#69](https://github.com/influxdata/influxdb-client-swift/pull/69) Updated `Point` to be a sendable struct
1. [#70](https://github.com/influxdata/influxdb-client-swift/pull/70): Improved usability of `Point` by adding tags, fields, and time to the initializer and making the properties public and mutable

## 1.7.0 [2024-05-17]

Expand Down
9 changes: 5 additions & 4 deletions Examples/AsyncAwait/Sources/AsyncAwait/AsyncAwait.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,11 @@ extension AsyncAwait {
//
// Asynchronous write
//
let point = InfluxDBClient
.Point("demo")
.addTag(key: "type", value: "point")
.addField(key: "value", value: .int(2))
let point = InfluxDBClient.Point(
"demo",
tags: ["type": "point"],
fields: ["value": .int(2)]
)
try await client.makeWriteAPI().write(point: point)
print("Written data:\n > \(try point.toLineProtocol())")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,16 @@ extension InvokableScriptsAPI {
//
// Prepare Data
//
let point1 = InfluxDBClient
.Point("my_measurement")
.addTag(key: "location", value: "Prague")
.addField(key: "temperature", value: .double(25.3))
let point2 = InfluxDBClient
.Point("my_measurement")
.addTag(key: "location", value: "New York")
.addField(key: "temperature", value: .double(24.3))
let point1 = InfluxDBClient.Point(
"my_measurement",
tags: ["location": "Prague"],
fields: ["temperature": .double(25.3)]
)
let point2 = InfluxDBClient.Point(
"my_measurement",
tags: ["location": "New York"],
fields: ["temperature": .double(24.3)]
)
try await client.makeWriteAPI().write(points: [point1, point2])

//
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,11 @@ extension ParameterizedQuery {
options: InfluxDBClient.InfluxDBOptions(bucket: bucket, org: org))

for index in 1...3 {
let point = InfluxDBClient
.Point("demo")
.addTag(key: "type", value: "point")
.addField(key: "value", value: .int(index))
let point = InfluxDBClient.Point(
"demo",
tags: ["type": "point"],
fields: ["value": .int(index)]
)
try await client.makeWriteAPI().write(point: point)
}

Expand Down
11 changes: 7 additions & 4 deletions Examples/RecordRow/Sources/RecordRow/RecordRow.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,13 @@ extension RecordRow {
// Write test data into InfluxDB
//
for i in 1...5 {
let point = InfluxDBClient
.Point("point")
.addField(key: "table", value: .string("my-table"))
.addField(key: "result", value: .double(Double(i)))
let point = InfluxDBClient.Point(
"point",
fields: [
"table": .string("my-table"),
"result": .double(Double(i)),
]
)
try await client.makeWriteAPI().write(point: point)
}

Expand Down
20 changes: 11 additions & 9 deletions Examples/WriteData/Sources/WriteData/WriteData.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,18 +35,20 @@ extension WriteData {
//
// Record defined as Data Point
//
let recordPoint = InfluxDBClient
.Point("demo")
.addTag(key: "type", value: "point")
.addField(key: "value", value: .int(2))
let recordPoint = InfluxDBClient.Point(
"demo",
tags: ["type": "point"],
fields: ["value": .int(2)]
)
//
// Record defined as Data Point with Timestamp
//
let recordPointDate = InfluxDBClient
.Point("demo")
.addTag(key: "type", value: "point-timestamp")
.addField(key: "value", value: .int(2))
.time(time: .date(Date()))
let recordPointDate = InfluxDBClient.Point(
"demo",
tags: ["type": "point-timestamp"],
fields: ["value": .int(2)],
time: .date(Date())
)

try await client.makeWriteAPI().write(points: [recordPoint, recordPointDate])
print("Written data:\n\n\([recordPoint, recordPointDate].map { "\t- \($0)" }.joined(separator: "\n"))")
Expand Down
19 changes: 11 additions & 8 deletions Examples/WriteDataInBatches/Sources/WriteDataInBatches/main.swift
Original file line number Diff line number Diff line change
Expand Up @@ -86,14 +86,17 @@ struct WriteDataInBatches: ParsableCommand {
/// - dateFormatter: for parsing date
/// - Returns: parsed InfluxDBClient.Point
private func toPoint(row: [String], dateFormatter: DateFormatter) -> InfluxDBClient.Point {
InfluxDBClient
.Point("financial-analysis")
.addTag(key: "type", value: "vix-daily")
.addField(key: "open", value: .double(Double(row[1])!))
.addField(key: "high", value: .double(Double(row[2])!))
.addField(key: "low", value: .double(Double(row[3])!))
.addField(key: "close", value: .double(Double(row[4])!))
.time(time: .date(dateFormatter.date(from: row[0])!))
InfluxDBClient.Point(
"financial-analysis",
tags: ["type": "vix-daily"],
fields: [
"open": .double(Double(row[1])!),
"high": .double(Double(row[2])!),
"low": .double(Double(row[3])!),
"close": .double(Double(row[4])!)
],
time: .date(dateFormatter.date(from: row[0])!)
)
}

private func atExit(client: InfluxDBClient, error: InfluxDBClient.InfluxDBError? = nil) {
Expand Down
22 changes: 14 additions & 8 deletions Package.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// swift-tools-version:5.3
// swift-tools-version:5.7
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription
Expand All @@ -11,21 +11,27 @@ let package = Package(
],
dependencies: [
// Dependencies declare other packages that this package depends on.
.package(name: "Gzip", url: "https://github.com/1024jp/GzipSwift", from: "5.1.1"),
.package(name: "CSV.swift", url: "https://github.com/yaslab/CSV.swift", from: "2.4.2"),
.package(name: "SwiftTestReporter", url: "https://github.com/allegro/swift-junit.git", from: "2.0.0"),
.package(name: "swift-log", url: "https://github.com/apple/swift-log.git", from: "1.0.0"),
.package(url: "https://github.com/1024jp/GzipSwift", from: "5.1.1"),
.package(url: "https://github.com/yaslab/CSV.swift", from: "2.4.2"),
.package(url: "https://github.com/allegro/swift-junit.git", from: "2.0.0"),
.package(url: "https://github.com/apple/swift-log.git", from: "1.0.0"),
],
targets: [
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
// Targets can depend on other targets in this package, and on products in packages this package depends on.
.target(name: "InfluxDBSwift", dependencies: [
"Gzip",
.product(name: "Gzip", package: "GzipSwift"),
.product(name: "CSV", package: "CSV.swift"),
.product(name: "Logging", package: "swift-log")
]),
.target(name: "InfluxDBSwiftApis", dependencies: ["InfluxDBSwift"]),
.testTarget(name: "InfluxDBSwiftTests", dependencies: ["InfluxDBSwift", "SwiftTestReporter"]),
.testTarget(name: "InfluxDBSwiftApisTests", dependencies: ["InfluxDBSwiftApis", "SwiftTestReporter"]),
.testTarget(name: "InfluxDBSwiftTests", dependencies: [
"InfluxDBSwift",
.product(name: "SwiftTestReporter", package: "swift-junit")
]),
.testTarget(name: "InfluxDBSwiftApisTests", dependencies: [
"InfluxDBSwiftApis",
.product(name: "SwiftTestReporter", package: "swift-junit")
]),
]
)
61 changes: 33 additions & 28 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ InfluxDB 2.x client consists of two packages

## Supported Platforms

This package requires Swift 5 and Xcode 12+.
This package requires Swift 5.7 and Xcode 14+.

- iOS 14.0+
- macOS 11.0+
Expand All @@ -70,24 +70,24 @@ This package requires Swift 5 and Xcode 12+.

Add this line to your `Package.swift` :

~~~swift
// swift-tools-version:5.3
```swift
// swift-tools-version:5.7
import PackageDescription

let package = Package(
name: "MyPackage",
dependencies: [
.package(name: "influxdb-client-swift", url: "https://github.com/influxdata/influxdb-client-swift", from: "1.7.0"),
.package(name: "influxdb-client-swift", url: "https://github.com/influxdata/influxdb-client-swift", from: "2.0.0"),
],
targets: [
.target(name: "MyModule", dependencies: [
.product(name: "InfluxDBSwift", package: "influxdb-client-swift"),
// or InfluxDBSwiftApis for management API
.product(name: "InfluxDBSwiftApis", package: "influxdb-client-swift")
.product(name: "InfluxDBSwift", package: "influxdb-client-swift"),
// or InfluxDBSwiftApis for management API
.product(name: "InfluxDBSwiftApis", package: "influxdb-client-swift")
])
]
)
~~~
```

## Usage

Expand Down Expand Up @@ -187,25 +187,27 @@ extension WriteData {
// Initialize Client with default Bucket and Organization
//
let client = InfluxDBClient(
url: url,
token: token,
options: InfluxDBClient.InfluxDBOptions(bucket: bucket, org: org))

url: url,
token: token,
options: InfluxDBClient.InfluxDBOptions(bucket: bucket, org: org)
)
//
// Record defined as Data Point
//
let recordPoint = InfluxDBClient
.Point("demo")
.addTag(key: "type", value: "point")
.addField(key: "value", value: .int(2))
let recordPoint = InfluxDBClient.Point(
"demo",
tags: ["type": "point"],
fields: ["value": .int(2)]
)
//
// Record defined as Data Point with Timestamp
//
let recordPointDate = InfluxDBClient
.Point("demo")
.addTag(key: "type", value: "point-timestamp")
.addField(key: "value", value: .int(2))
.time(time: .date(Date()))
let recordPointDate = InfluxDBClient.Point(
"demo",
tags: ["type": "point-timestamp"],
fields: ["value": .int(2)],
time: .date(Date())
)

try await client.makeWriteAPI().write(points: [recordPoint, recordPointDate])
print("Written data:\n\n\([recordPoint, recordPointDate].map { "\t- \($0)" }.joined(separator: "\n"))")
Expand Down Expand Up @@ -375,10 +377,11 @@ extension ParameterizedQuery {
options: InfluxDBClient.InfluxDBOptions(bucket: bucket, org: org))

for index in 1...3 {
let point = InfluxDBClient
.Point("demo")
.addTag(key: "type", value: "point")
.addField(key: "value", value: .int(index))
let point = InfluxDBClient.Point(
"demo",
tags: ["type": "point"],
fields: ["value", value: .int(index)]
)
try await client.makeWriteAPI().write(point: point)
}

Expand Down Expand Up @@ -602,9 +605,11 @@ let tuple: InfluxDBClient.Point.Tuple
= (measurement: "mem", tags: ["tag": "a"], fields: ["value": .int(3)], time: nil)

let records: [Any] = [
InfluxDBClient.Point("mining")
.addTag(key: "sensor_state", value: "normal")
.addField(key: "depth", value: .int(2)),
InfluxDBClient.Point(
"mining",
tags: ["sensor_state": "normal"],
fields: ["depth": .int(2)]
),
tuple
]

Expand Down
4 changes: 2 additions & 2 deletions Sources/InfluxDBSwift/InfluxDBClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import FoundationNetworking
/// ````
public struct InfluxDBClient {
/// Version of client.
public static var version: String = "1.8.0dev"
public static var version: String = "2.0.0dev"
/// InfluxDB host and port.
public let url: String
/// Authentication token.
Expand Down Expand Up @@ -247,7 +247,7 @@ extension InfluxDBClient {

/// An enum represents the precision for the unix timestamps within the body line-protocol.
/// - SeeAlso: https://docs.influxdata.com/influxdb/latest/write-data/#timestamp-precision
public enum TimestampPrecision: String, Codable, CaseIterable {
public enum TimestampPrecision: String, Codable, CaseIterable, Sendable {
/// Milliseconds
case ms
/// Seconds
Expand Down
Loading
Loading