@quenty/influxdbclient 7.37.0 → 7.39.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,16 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ # [7.39.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/influxdbclient@7.38.0...@quenty/influxdbclient@7.39.0) (2026-07-22)
7
+
8
+ ### Features
9
+
10
+ - Add tests to InfluxDBClient package ([c2b138f](https://github.com/Quenty/NevermoreEngine/commit/c2b138f0c0ed050dd6cb3541f644b766b5db6b10))
11
+
12
+ # [7.38.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/influxdbclient@7.37.0...@quenty/influxdbclient@7.38.0) (2026-07-21)
13
+
14
+ **Note:** Version bump only for package @quenty/influxdbclient
15
+
6
16
  # [7.37.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/influxdbclient@7.36.0...@quenty/influxdbclient@7.37.0) (2026-07-18)
7
17
 
8
18
  ### Bug Fixes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quenty/influxdbclient",
3
- "version": "7.37.0",
3
+ "version": "7.39.0",
4
4
  "description": "Provides a Roblox Lua InfluxDB client",
5
5
  "keywords": [
6
6
  "Roblox",
@@ -47,5 +47,5 @@
47
47
  "publishConfig": {
48
48
  "access": "public"
49
49
  },
50
- "gitHead": "647acfad93dca41c38f59cda247d2bfc0fff36d4"
50
+ "gitHead": "93f15b200c0f465a0b5304fcf05f5cfe7fdcbd1d"
51
51
  }
@@ -0,0 +1,86 @@
1
+ --!strict
2
+ --[[
3
+ @class InfluxDBClientConfigUtils.spec.lua
4
+ ]]
5
+
6
+ local require = require(script.Parent.loader).load(script)
7
+
8
+ local InfluxDBClientConfigUtils = require("InfluxDBClientConfigUtils")
9
+ local Jest = require("Jest")
10
+
11
+ local describe = Jest.Globals.describe
12
+ local expect = Jest.Globals.expect
13
+ local it = Jest.Globals.it
14
+
15
+ describe("InfluxDBClientConfigUtils.isClientConfig", function()
16
+ it("should be true for a config with a string token", function()
17
+ expect(InfluxDBClientConfigUtils.isClientConfig({
18
+ url = "https://us-east-1-1.aws.cloud2.influxdata.com",
19
+ token = "my-token",
20
+ })).toEqual(true)
21
+ end)
22
+
23
+ it("should be false for a non-table", function()
24
+ expect(InfluxDBClientConfigUtils.isClientConfig(nil)).toEqual(false)
25
+ expect(InfluxDBClientConfigUtils.isClientConfig("str")).toEqual(false)
26
+ expect(InfluxDBClientConfigUtils.isClientConfig(5)).toEqual(false)
27
+ end)
28
+
29
+ it("should be false when url is missing", function()
30
+ expect(InfluxDBClientConfigUtils.isClientConfig({
31
+ token = "my-token",
32
+ })).toEqual(false)
33
+ end)
34
+
35
+ it("should be false when url is not a string", function()
36
+ expect(InfluxDBClientConfigUtils.isClientConfig({
37
+ url = 5,
38
+ token = "my-token",
39
+ })).toEqual(false)
40
+ end)
41
+
42
+ it("should be false when token is missing", function()
43
+ expect(InfluxDBClientConfigUtils.isClientConfig({
44
+ url = "https://example.com",
45
+ })).toEqual(false)
46
+ end)
47
+
48
+ it("should be false when token is a number", function()
49
+ expect(InfluxDBClientConfigUtils.isClientConfig({
50
+ url = "https://example.com",
51
+ token = 5,
52
+ })).toEqual(false)
53
+ end)
54
+ end)
55
+
56
+ describe("InfluxDBClientConfigUtils.createClientConfig", function()
57
+ it("should return a config with only url and token fields", function()
58
+ local config = InfluxDBClientConfigUtils.createClientConfig({
59
+ url = "https://example.com",
60
+ token = "my-token",
61
+ extra = "ignored",
62
+ } :: any)
63
+
64
+ expect(config.url).toEqual("https://example.com")
65
+ expect(config.token).toEqual("my-token")
66
+ expect((config :: any).extra).toEqual(nil)
67
+ end)
68
+
69
+ it("should return a fresh table, not the same reference", function()
70
+ local input = {
71
+ url = "https://example.com",
72
+ token = "my-token",
73
+ }
74
+ local config = InfluxDBClientConfigUtils.createClientConfig(input)
75
+
76
+ expect(config).never.toBe(input)
77
+ end)
78
+
79
+ it("should throw on an invalid config", function()
80
+ expect(function()
81
+ InfluxDBClientConfigUtils.createClientConfig({
82
+ token = "my-token",
83
+ } :: any)
84
+ end).toThrow("Bad config")
85
+ end)
86
+ end)
@@ -0,0 +1,94 @@
1
+ --!strict
2
+ --[[
3
+ @class InfluxDBWriteOptionUtils.spec.lua
4
+ ]]
5
+
6
+ local require = require(script.Parent.loader).load(script)
7
+
8
+ local InfluxDBWriteOptionUtils = require("InfluxDBWriteOptionUtils")
9
+ local Jest = require("Jest")
10
+
11
+ local describe = Jest.Globals.describe
12
+ local expect = Jest.Globals.expect
13
+ local it = Jest.Globals.it
14
+
15
+ describe("InfluxDBWriteOptionUtils.getDefaultOptions", function()
16
+ it("should return the documented defaults", function()
17
+ local options = InfluxDBWriteOptionUtils.getDefaultOptions()
18
+
19
+ expect(options.batchSize).toEqual(1000)
20
+ expect(options.maxBatchBytes).toEqual(50_000_000)
21
+ expect(options.flushIntervalSeconds).toEqual(60)
22
+ end)
23
+
24
+ it("should return a readonly table", function()
25
+ local options = InfluxDBWriteOptionUtils.getDefaultOptions()
26
+
27
+ expect(function()
28
+ (options :: any).batchSize = 5
29
+ end).toThrow()
30
+ end)
31
+ end)
32
+
33
+ describe("InfluxDBWriteOptionUtils.isWriteOptions", function()
34
+ it("should be true for a fully specified options table", function()
35
+ expect(InfluxDBWriteOptionUtils.isWriteOptions({
36
+ batchSize = 10,
37
+ maxBatchBytes = 1000,
38
+ flushIntervalSeconds = 5,
39
+ })).toEqual(true)
40
+ end)
41
+
42
+ it("should be false for a non-table", function()
43
+ expect(InfluxDBWriteOptionUtils.isWriteOptions(nil)).toEqual(false)
44
+ expect(InfluxDBWriteOptionUtils.isWriteOptions("str")).toEqual(false)
45
+ end)
46
+
47
+ it("should be false when batchSize is missing", function()
48
+ expect(InfluxDBWriteOptionUtils.isWriteOptions({
49
+ maxBatchBytes = 1000,
50
+ flushIntervalSeconds = 5,
51
+ })).toEqual(false)
52
+ end)
53
+
54
+ it("should be false when maxBatchBytes is not a number", function()
55
+ expect(InfluxDBWriteOptionUtils.isWriteOptions({
56
+ batchSize = 10,
57
+ maxBatchBytes = "1000",
58
+ flushIntervalSeconds = 5,
59
+ })).toEqual(false)
60
+ end)
61
+
62
+ it("should be false when flushIntervalSeconds is missing", function()
63
+ expect(InfluxDBWriteOptionUtils.isWriteOptions({
64
+ batchSize = 10,
65
+ maxBatchBytes = 1000,
66
+ })).toEqual(false)
67
+ end)
68
+ end)
69
+
70
+ describe("InfluxDBWriteOptionUtils.createWriteOptions", function()
71
+ it("should return a readonly copy of valid options", function()
72
+ local options = InfluxDBWriteOptionUtils.createWriteOptions({
73
+ batchSize = 10,
74
+ maxBatchBytes = 1000,
75
+ flushIntervalSeconds = 5,
76
+ })
77
+
78
+ expect(options.batchSize).toEqual(10)
79
+ expect(options.maxBatchBytes).toEqual(1000)
80
+ expect(options.flushIntervalSeconds).toEqual(5)
81
+
82
+ expect(function()
83
+ (options :: any).batchSize = 20
84
+ end).toThrow()
85
+ end)
86
+
87
+ it("should throw on invalid options", function()
88
+ expect(function()
89
+ InfluxDBWriteOptionUtils.createWriteOptions({
90
+ batchSize = 10,
91
+ } :: any)
92
+ end).toThrow("Bad options")
93
+ end)
94
+ end)
@@ -10,6 +10,7 @@ local require = require(script.Parent.loader).load(script)
10
10
 
11
11
  local BaseObject = require("BaseObject")
12
12
  local InfluxDBClientConfigUtils = require("InfluxDBClientConfigUtils")
13
+ local InfluxDBRequestHandlerMock = require("InfluxDBRequestHandlerMock")
13
14
  local InfluxDBWriteAPI = require("InfluxDBWriteAPI")
14
15
  local Maid = require("Maid")
15
16
  local Promise = require("Promise")
@@ -26,6 +27,7 @@ export type InfluxDBClient =
26
27
  _clientConfig: ValueObject.ValueObject<InfluxDBClientConfigUtils.InfluxDBClientConfig>,
27
28
  _writeApis: { [string]: { [string]: InfluxDBWriteAPI.InfluxDBWriteAPI } },
28
29
  _flushAllPromises: Promise.Promise<()>,
30
+ _requestHandler: InfluxDBWriteAPI.InfluxDBRequestHandler?,
29
31
  },
30
32
  {} :: typeof({ __index = InfluxDBClient })
31
33
  ))
@@ -35,11 +37,20 @@ export type InfluxDBClient =
35
37
  Creates a new InfluxDB client
36
38
 
37
39
  @param clientConfig InfluxDBClientConfig?
40
+ @param requestHandler InfluxDBRequestHandler? -- Defaults to [HttpPromise.request]. Inject a mock to avoid real HTTP.
38
41
  @return InfluxDBClient
39
42
  ]=]
40
- function InfluxDBClient.new(clientConfig: InfluxDBClientConfigUtils.InfluxDBClientConfig?): InfluxDBClient
43
+ function InfluxDBClient.new(
44
+ clientConfig: InfluxDBClientConfigUtils.InfluxDBClientConfig?,
45
+ requestHandler: InfluxDBWriteAPI.InfluxDBRequestHandler?
46
+ ): InfluxDBClient
41
47
  local self: InfluxDBClient = setmetatable(BaseObject.new() :: any, InfluxDBClient)
42
48
 
49
+ assert(type(requestHandler) == "function" or requestHandler == nil, "Bad requestHandler")
50
+
51
+ -- Threaded down into each write API created by GetWriteAPI so all of them share the same seam.
52
+ self._requestHandler = requestHandler
53
+
43
54
  self._clientConfig = self._maid:Add(ValueObject.new(nil))
44
55
 
45
56
  if clientConfig then
@@ -51,6 +62,33 @@ function InfluxDBClient.new(clientConfig: InfluxDBClientConfigUtils.InfluxDBClie
51
62
  return self
52
63
  end
53
64
 
65
+ --[=[
66
+ Creates a new InfluxDB client wired to an [InfluxDBRequestHandlerMock] so no real HTTP calls are
67
+ made. Returns both the client and the mock, so a test can inspect the requests it would have sent.
68
+
69
+ ```lua
70
+ local client, requestMock = InfluxDBClient.newMock()
71
+ client:SetClientConfig({ url = "https://example.com", token = "token" })
72
+
73
+ local writeAPI = client:GetWriteAPI("org", "bucket")
74
+ writeAPI:QueuePoint(point)
75
+ writeAPI:PromiseFlush():Wait()
76
+
77
+ print(#requestMock:GetRequests()) --> 1
78
+ ```
79
+
80
+ @param clientConfig InfluxDBClientConfig?
81
+ @return (InfluxDBClient, InfluxDBRequestHandlerMock)
82
+ ]=]
83
+ function InfluxDBClient.newMock(
84
+ clientConfig: InfluxDBClientConfigUtils.InfluxDBClientConfig?
85
+ ): (InfluxDBClient, InfluxDBRequestHandlerMock.InfluxDBRequestHandlerMock)
86
+ local requestMock = InfluxDBRequestHandlerMock.new()
87
+ local client = InfluxDBClient.new(clientConfig, requestMock.Handler)
88
+
89
+ return client, requestMock
90
+ end
91
+
54
92
  --[=[
55
93
  Sets the client config for this client
56
94
 
@@ -83,10 +121,14 @@ function InfluxDBClient.GetWriteAPI(
83
121
 
84
122
  local maid = Maid.new()
85
123
 
86
- local writeAPI = maid:Add(InfluxDBWriteAPI.new(org, bucket, precision))
124
+ local writeAPI = maid:Add(InfluxDBWriteAPI.new(org, bucket, precision, self._requestHandler))
87
125
 
88
126
  maid:GiveTask(self._clientConfig:Observe():Subscribe(function(clientConfig)
89
- writeAPI:SetClientConfig(clientConfig)
127
+ -- The observable fires the current value immediately, which is nil until a config is set. Guard
128
+ -- so GetWriteAPI can be called before SetClientConfig; the later config is pushed through here.
129
+ if clientConfig then
130
+ writeAPI:SetClientConfig(clientConfig)
131
+ end
90
132
  end))
91
133
 
92
134
  maid:GiveTask(writeAPI.Destroying:Connect(function()
@@ -0,0 +1,227 @@
1
+ --!strict
2
+ --[[
3
+ @class InfluxDBClient.spec.lua
4
+ ]]
5
+
6
+ local require = require(script.Parent.loader).load(script)
7
+
8
+ local InfluxDBClient = require("InfluxDBClient")
9
+ local InfluxDBPoint = require("InfluxDBPoint")
10
+ local InfluxDBRequestHandlerMock = require("InfluxDBRequestHandlerMock")
11
+ local Jest = require("Jest")
12
+ local Promise = require("Promise")
13
+ local PromiseTestUtils = require("PromiseTestUtils")
14
+
15
+ local describe = Jest.Globals.describe
16
+ local expect = Jest.Globals.expect
17
+ local it = Jest.Globals.it
18
+
19
+ local FIXED_TIMESTAMP = DateTime.fromUnixTimestampMillis(1600000000000)
20
+
21
+ local CONFIG = {
22
+ url = "https://example.com",
23
+ token = "my-token",
24
+ }
25
+
26
+ local function newPoint(): InfluxDBPoint.InfluxDBPoint
27
+ local point = InfluxDBPoint.new("temperature")
28
+ point:SetTimestamp(FIXED_TIMESTAMP)
29
+ point:AddFloatField("value", 23.5)
30
+ return point
31
+ end
32
+
33
+ describe("InfluxDBClient.new", function()
34
+ it("should construct without a config", function()
35
+ local client = InfluxDBClient.new()
36
+ expect(client.ClassName).toEqual("InfluxDBClient")
37
+ client:Destroy()
38
+ end)
39
+
40
+ it("should construct with a config", function()
41
+ local client = InfluxDBClient.new(CONFIG)
42
+ expect(client.ClassName).toEqual("InfluxDBClient")
43
+ client:Destroy()
44
+ end)
45
+
46
+ it("should throw when constructed with an invalid config", function()
47
+ expect(function()
48
+ InfluxDBClient.new({ url = "https://example.com" } :: any)
49
+ end).toThrow("Bad clientConfig")
50
+ end)
51
+
52
+ it("should throw on a non-function, non-nil request handler", function()
53
+ expect(function()
54
+ InfluxDBClient.new(nil, 5 :: any)
55
+ end).toThrow("Bad requestHandler")
56
+ end)
57
+ end)
58
+
59
+ describe("InfluxDBClient.newMock", function()
60
+ it("should return a client and a request handler mock", function()
61
+ local client, requestMock = InfluxDBClient.newMock()
62
+
63
+ expect(client.ClassName).toEqual("InfluxDBClient")
64
+ expect(InfluxDBRequestHandlerMock.isInfluxDBRequestHandlerMock(requestMock)).toEqual(true)
65
+
66
+ client:Destroy()
67
+ end)
68
+
69
+ it("should route write API traffic through the mock instead of the network", function()
70
+ local client, requestMock = InfluxDBClient.newMock(CONFIG)
71
+
72
+ local writeAPI = client:GetWriteAPI("my-org", "my-bucket")
73
+ writeAPI:QueuePoint(newPoint())
74
+ expect(PromiseTestUtils.awaitSettled(writeAPI:PromiseFlush())).toEqual(true)
75
+
76
+ expect(#requestMock:GetRequests()).toEqual(1)
77
+ expect((requestMock:GetLastRequest() :: any).Headers.Authorization).toEqual("Token my-token")
78
+
79
+ client:Destroy()
80
+ end)
81
+ end)
82
+
83
+ describe("InfluxDBClient.SetClientConfig", function()
84
+ it("should throw on an invalid config", function()
85
+ local client = InfluxDBClient.new()
86
+
87
+ expect(function()
88
+ client:SetClientConfig({ token = "my-token" } :: any)
89
+ end).toThrow("Bad clientConfig")
90
+
91
+ client:Destroy()
92
+ end)
93
+ end)
94
+
95
+ describe("InfluxDBClient.GetWriteAPI", function()
96
+ it("should throw on a non-string org", function()
97
+ local client = InfluxDBClient.new()
98
+ expect(function()
99
+ client:GetWriteAPI(5 :: any, "my-bucket")
100
+ end).toThrow("Bad org")
101
+ client:Destroy()
102
+ end)
103
+
104
+ it("should throw on a non-string bucket", function()
105
+ local client = InfluxDBClient.new()
106
+ expect(function()
107
+ client:GetWriteAPI("my-org", 5 :: any)
108
+ end).toThrow("Bad bucket")
109
+ client:Destroy()
110
+ end)
111
+
112
+ it("should throw on a non-string, non-nil precision", function()
113
+ local client = InfluxDBClient.new()
114
+ expect(function()
115
+ client:GetWriteAPI("my-org", "my-bucket", 5 :: any)
116
+ end).toThrow("Bad precision")
117
+ client:Destroy()
118
+ end)
119
+
120
+ -- Regression: GetWriteAPI must work before a config is set. Its ValueObject:Observe() subscription
121
+ -- fires the current value (nil) immediately; without a nil guard in GetWriteAPI this would call
122
+ -- writeAPI:SetClientConfig(nil) and throw "Bad clientConfig".
123
+ it("should return a write API", function()
124
+ local client = InfluxDBClient.new()
125
+ local writeAPI = client:GetWriteAPI("my-org", "my-bucket")
126
+ expect(writeAPI.ClassName).toEqual("InfluxDBWriteAPI")
127
+ client:Destroy()
128
+ end)
129
+
130
+ it("should return the same write API for the same org and bucket", function()
131
+ local client = InfluxDBClient.new()
132
+ local first = client:GetWriteAPI("my-org", "my-bucket")
133
+ local second = client:GetWriteAPI("my-org", "my-bucket")
134
+ expect(second).toBe(first)
135
+ client:Destroy()
136
+ end)
137
+
138
+ it("should return a different write API for a different bucket", function()
139
+ local client = InfluxDBClient.new()
140
+ local first = client:GetWriteAPI("my-org", "bucket-a")
141
+ local second = client:GetWriteAPI("my-org", "bucket-b")
142
+ expect(second).never.toBe(first)
143
+ client:Destroy()
144
+ end)
145
+
146
+ it("should return a different write API for a different org", function()
147
+ local client = InfluxDBClient.new()
148
+ local first = client:GetWriteAPI("org-a", "my-bucket")
149
+ local second = client:GetWriteAPI("org-b", "my-bucket")
150
+ expect(second).never.toBe(first)
151
+ client:Destroy()
152
+ end)
153
+
154
+ it("should propagate the client config set before GetWriteAPI to the write API", function()
155
+ local client, requestMock = InfluxDBClient.newMock(CONFIG)
156
+ local writeAPI = client:GetWriteAPI("my-org", "my-bucket")
157
+
158
+ -- If the config had not reached the write API, the flush would reject with "No client configuration".
159
+ writeAPI:QueuePoint(newPoint())
160
+ expect(PromiseTestUtils.awaitSettled(writeAPI:PromiseFlush())).toEqual(true)
161
+
162
+ expect(#requestMock:GetRequests()).toEqual(1)
163
+
164
+ client:Destroy()
165
+ end)
166
+
167
+ it("should propagate a client config set after GetWriteAPI to the write API", function()
168
+ local client, requestMock = InfluxDBClient.newMock()
169
+ local writeAPI = client:GetWriteAPI("my-org", "my-bucket")
170
+
171
+ client:SetClientConfig(CONFIG)
172
+
173
+ writeAPI:QueuePoint(newPoint())
174
+ expect(PromiseTestUtils.awaitSettled(writeAPI:PromiseFlush())).toEqual(true)
175
+
176
+ expect(#requestMock:GetRequests()).toEqual(1)
177
+
178
+ client:Destroy()
179
+ end)
180
+ end)
181
+
182
+ describe("InfluxDBClient.PromiseFlushAll", function()
183
+ it("should resolve when there are no write APIs", function()
184
+ local client = InfluxDBClient.new()
185
+
186
+ expect(PromiseTestUtils.awaitSettled(client:PromiseFlushAll())).toEqual(true)
187
+
188
+ client:Destroy()
189
+ end)
190
+
191
+ it("should flush buffered points across every write API", function()
192
+ local client, requestMock = InfluxDBClient.newMock(CONFIG)
193
+
194
+ local apiA = client:GetWriteAPI("my-org", "bucket-a")
195
+ local apiB = client:GetWriteAPI("my-org", "bucket-b")
196
+ apiA:QueuePoint(newPoint())
197
+ apiB:QueuePoint(newPoint())
198
+
199
+ expect(PromiseTestUtils.awaitSettled(client:PromiseFlushAll())).toEqual(true)
200
+ expect(#requestMock:GetRequests()).toEqual(2)
201
+
202
+ client:Destroy()
203
+ end)
204
+
205
+ it("should reuse the pending flush promise while one is in flight", function()
206
+ local client, requestMock = InfluxDBClient.newMock(CONFIG)
207
+
208
+ -- A request that never settles keeps the flush pending, so both calls observe the same promise.
209
+ requestMock:SetResponder(function()
210
+ return Promise.new(function() end)
211
+ end)
212
+
213
+ local writeAPI = client:GetWriteAPI("my-org", "my-bucket")
214
+ writeAPI:QueuePoint(newPoint())
215
+
216
+ local first = client:PromiseFlushAll()
217
+ local second = client:PromiseFlushAll()
218
+
219
+ expect(second).toBe(first)
220
+
221
+ -- Destroy cancels the in-flight request, rejecting this promise; consume it so the cancellation
222
+ -- does not surface as an unhandled rejection.
223
+ first:Catch(function() end)
224
+
225
+ client:Destroy()
226
+ end)
227
+ end)
@@ -0,0 +1,147 @@
1
+ --!strict
2
+ --[=[
3
+ Centralized service using serviceBag. Lets other packages share a single [InfluxDBClient] and, in
4
+ tests, swap the underlying request implementation for an [InfluxDBRequestHandlerMock] at the
5
+ ServiceBag layer -- the same pattern as [PlayerDataStoreService.SetRobloxDataStore].
6
+
7
+ ```lua
8
+ -- Production
9
+ local influxDBService = serviceBag:GetService(require("InfluxDBService"))
10
+ -- ...after Init, before first use...
11
+ influxDBService:SetClientConfig({ url = "https://example.com", token = "token" })
12
+
13
+ local writeAPI = influxDBService:GetWriteAPI("org", "bucket")
14
+ writeAPI:QueuePoint(point)
15
+ ```
16
+
17
+ ```lua
18
+ -- Tests: inject a mock so nothing hits the network
19
+ local requestMock = InfluxDBRequestHandlerMock.new()
20
+ influxDBService:SetRequestHandler(requestMock.Handler)
21
+ ```
22
+
23
+ @server
24
+ @class InfluxDBService
25
+ ]=]
26
+
27
+ local require = require(script.Parent.loader).load(script)
28
+
29
+ local InfluxDBClient = require("InfluxDBClient")
30
+ local InfluxDBClientConfigUtils = require("InfluxDBClientConfigUtils")
31
+ local InfluxDBWriteAPI = require("InfluxDBWriteAPI")
32
+ local Maid = require("Maid")
33
+ local Promise = require("Promise")
34
+ local ServiceBag = require("ServiceBag")
35
+
36
+ local InfluxDBService = {}
37
+ InfluxDBService.ServiceName = "InfluxDBService"
38
+
39
+ export type InfluxDBService = typeof(setmetatable(
40
+ {} :: {
41
+ _serviceBag: ServiceBag.ServiceBag,
42
+ _maid: Maid.Maid,
43
+ _client: InfluxDBClient.InfluxDBClient?,
44
+ _requestHandler: InfluxDBWriteAPI.InfluxDBRequestHandler?,
45
+ _pendingClientConfig: InfluxDBClientConfigUtils.InfluxDBClientConfig?,
46
+ },
47
+ {} :: typeof({ __index = InfluxDBService })
48
+ ))
49
+
50
+ --[=[
51
+ Initializes the InfluxDBService. Should be done via [ServiceBag.Init].
52
+
53
+ @param serviceBag ServiceBag
54
+ ]=]
55
+ function InfluxDBService.Init(self: InfluxDBService, serviceBag: ServiceBag.ServiceBag): ()
56
+ self._serviceBag = assert(serviceBag, "No serviceBag")
57
+ self._maid = Maid.new()
58
+ end
59
+
60
+ --[=[
61
+ Injects the request handler the underlying client uses to send data, instead of the real
62
+ [HttpPromise.request]. Pass an [InfluxDBRequestHandlerMock] handler so tests never hit the network.
63
+ Intended for testing; must be called before the client is first built.
64
+
65
+ @param requestHandler InfluxDBRequestHandler
66
+ ]=]
67
+ function InfluxDBService.SetRequestHandler(
68
+ self: InfluxDBService,
69
+ requestHandler: InfluxDBWriteAPI.InfluxDBRequestHandler
70
+ ): ()
71
+ assert(type(requestHandler) == "function", "Bad requestHandler")
72
+ assert(not self._client, "Already built client, cannot override requestHandler")
73
+
74
+ self._requestHandler = requestHandler
75
+ end
76
+
77
+ --[=[
78
+ Sets the client config used to authenticate writes. May be called before or after the client is
79
+ built; a later config is forwarded to the existing client.
80
+
81
+ @param clientConfig InfluxDBClientConfig
82
+ ]=]
83
+ function InfluxDBService.SetClientConfig(
84
+ self: InfluxDBService,
85
+ clientConfig: InfluxDBClientConfigUtils.InfluxDBClientConfig
86
+ ): ()
87
+ assert(InfluxDBClientConfigUtils.isClientConfig(clientConfig), "Bad clientConfig")
88
+
89
+ self._pendingClientConfig = clientConfig
90
+
91
+ if self._client then
92
+ self._client:SetClientConfig(clientConfig)
93
+ end
94
+ end
95
+
96
+ --[=[
97
+ Returns the shared [InfluxDBClient], building it on first use with any injected request handler and
98
+ client config.
99
+
100
+ @return InfluxDBClient
101
+ ]=]
102
+ function InfluxDBService.GetClient(self: InfluxDBService): InfluxDBClient.InfluxDBClient
103
+ if self._client then
104
+ return self._client
105
+ end
106
+
107
+ local client = self._maid:Add(InfluxDBClient.new(self._pendingClientConfig, self._requestHandler))
108
+ self._client = client
109
+
110
+ return client
111
+ end
112
+
113
+ --[=[
114
+ Returns the write API for the given org and bucket from the shared client.
115
+
116
+ @param org string
117
+ @param bucket string
118
+ @param precision string?
119
+ @return InfluxDBWriteAPI
120
+ ]=]
121
+ function InfluxDBService.GetWriteAPI(
122
+ self: InfluxDBService,
123
+ org: string,
124
+ bucket: string,
125
+ precision: string?
126
+ ): InfluxDBWriteAPI.InfluxDBWriteAPI
127
+ return self:GetClient():GetWriteAPI(org, bucket, precision)
128
+ end
129
+
130
+ --[=[
131
+ Flushes every write API on the shared client. Resolves immediately if the client was never built.
132
+
133
+ @return Promise<()>
134
+ ]=]
135
+ function InfluxDBService.PromiseFlushAll(self: InfluxDBService): Promise.Promise<()>
136
+ if not self._client then
137
+ return Promise.resolved()
138
+ end
139
+
140
+ return self._client:PromiseFlushAll()
141
+ end
142
+
143
+ function InfluxDBService.Destroy(self: InfluxDBService): ()
144
+ self._maid:DoCleaning()
145
+ end
146
+
147
+ return InfluxDBService