influxdata-plugin-utils 0.1.0__tar.gz → 0.3.0__tar.gz
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.
- influxdata_plugin_utils-0.3.0/CHANGELOG.md +63 -0
- {influxdata_plugin_utils-0.1.0 → influxdata_plugin_utils-0.3.0}/PKG-INFO +27 -4
- {influxdata_plugin_utils-0.1.0 → influxdata_plugin_utils-0.3.0}/README.md +25 -2
- {influxdata_plugin_utils-0.1.0 → influxdata_plugin_utils-0.3.0}/pyproject.toml +1 -1
- {influxdata_plugin_utils-0.1.0 → influxdata_plugin_utils-0.3.0}/src/influxdata_plugin_utils/__init__.py +1 -1
- {influxdata_plugin_utils-0.1.0 → influxdata_plugin_utils-0.3.0}/src/influxdata_plugin_utils/config.py +13 -2
- {influxdata_plugin_utils-0.1.0 → influxdata_plugin_utils-0.3.0}/src/influxdata_plugin_utils/introspection.py +63 -11
- {influxdata_plugin_utils-0.1.0 → influxdata_plugin_utils-0.3.0}/src/influxdata_plugin_utils/parsing.py +3 -1
- {influxdata_plugin_utils-0.1.0 → influxdata_plugin_utils-0.3.0}/src/influxdata_plugin_utils/write.py +25 -4
- influxdata_plugin_utils-0.1.0/CHANGELOG.md +0 -26
- {influxdata_plugin_utils-0.1.0 → influxdata_plugin_utils-0.3.0}/.gitignore +0 -0
- {influxdata_plugin_utils-0.1.0 → influxdata_plugin_utils-0.3.0}/LICENSE-APACHE +0 -0
- {influxdata_plugin_utils-0.1.0 → influxdata_plugin_utils-0.3.0}/LICENSE-MIT +0 -0
- {influxdata_plugin_utils-0.1.0 → influxdata_plugin_utils-0.3.0}/src/influxdata_plugin_utils/cache.py +0 -0
- {influxdata_plugin_utils-0.1.0 → influxdata_plugin_utils-0.3.0}/src/influxdata_plugin_utils/py.typed +0 -0
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [0.3.0] - 2026-07-31
|
|
11
|
+
|
|
12
|
+
### Security
|
|
13
|
+
|
|
14
|
+
- `config.load_plugin_config` — disable dynaconf's `@` token substitution
|
|
15
|
+
(`@read_file`, `@format`, `@jinja`, `@get`, and ~30 others) by constructing
|
|
16
|
+
the settings object with `AUTO_CAST_FOR_DYNACONF=False`. Previously any
|
|
17
|
+
string value beginning with `@` was evaluated, so an untrusted value from an
|
|
18
|
+
HTTP request body could read the server's files or environment variables
|
|
19
|
+
(for example `@read_file /etc/passwd` or `@format {env[SECRET]}`). Values are
|
|
20
|
+
now always treated as literal data. See
|
|
21
|
+
[#134](https://github.com/influxdata/influxdb3_plugins/issues/134).
|
|
22
|
+
|
|
23
|
+
### Changed
|
|
24
|
+
|
|
25
|
+
- Pin `dynaconf>=3.2,<4` so a future major release cannot silently re-enable
|
|
26
|
+
token substitution.
|
|
27
|
+
|
|
28
|
+
## [0.2.0] - 2026-07-12
|
|
29
|
+
|
|
30
|
+
### Added
|
|
31
|
+
|
|
32
|
+
- `write.write_data` — optional `database` parameter for writing to another
|
|
33
|
+
database.
|
|
34
|
+
- `introspection` — optional `database` parameter for schema helpers and
|
|
35
|
+
`query_window`.
|
|
36
|
+
- `parsing.parse_timedelta` — `ms` (milliseconds) and `us` (microseconds)
|
|
37
|
+
duration units.
|
|
38
|
+
|
|
39
|
+
### Changed
|
|
40
|
+
|
|
41
|
+
- `write.write_data` — `no_sync` now defaults to `None`: writes go through
|
|
42
|
+
`write` / `write_to_db` (available on all InfluxDB 3 versions); passing a
|
|
43
|
+
boolean switches to `write_sync` / `write_sync_to_db` (InfluxDB 3.8+).
|
|
44
|
+
|
|
45
|
+
## [0.1.0] - 2026-07-08
|
|
46
|
+
|
|
47
|
+
### Added
|
|
48
|
+
|
|
49
|
+
- `config` — dynaconf-backed config loading (`load_plugin_config`), plugin
|
|
50
|
+
directory resolution (`resolve_plugin_dir`, `resolve_path`), re-exported
|
|
51
|
+
`Validator`.
|
|
52
|
+
- `introspection` — schema helpers (`get_table_names`, `get_tag_names`,
|
|
53
|
+
`get_field_names`) and `query_window`, with optional TTL caching.
|
|
54
|
+
- `parsing` — `parse_timedelta`, `parse_timestamp_ns`, `parse_int`,
|
|
55
|
+
`parse_bool`, `parse_delimited_list`, `parse_key_value`.
|
|
56
|
+
- `cache` — `cached` TTL wrapper over `influxdb3_local.cache`.
|
|
57
|
+
- `write` — `build_line`, `build_line_typed`, `add_field_with_type`,
|
|
58
|
+
`write_data` (batching + retry), `BatchLines`.
|
|
59
|
+
|
|
60
|
+
[Unreleased]: https://github.com/influxdata/influxdb3_plugins/compare/utils-v0.3.0...HEAD
|
|
61
|
+
[0.3.0]: https://github.com/influxdata/influxdb3_plugins/compare/utils-v0.2.0...utils-v0.3.0
|
|
62
|
+
[0.2.0]: https://github.com/influxdata/influxdb3_plugins/compare/utils-v0.1.0...utils-v0.2.0
|
|
63
|
+
[0.1.0]: https://github.com/influxdata/influxdb3_plugins/releases/tag/utils-v0.1.0
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: influxdata-plugin-utils
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: Shared helpers for InfluxDB 3 plugins.
|
|
5
5
|
Project-URL: Homepage, https://github.com/influxdata/influxdb3_plugins
|
|
6
6
|
Project-URL: Repository, https://github.com/influxdata/influxdb3_plugins
|
|
@@ -12,7 +12,7 @@ Keywords: influxdb,influxdb3,plugins
|
|
|
12
12
|
Classifier: Operating System :: OS Independent
|
|
13
13
|
Classifier: Programming Language :: Python :: 3.11
|
|
14
14
|
Requires-Python: >=3.11
|
|
15
|
-
Requires-Dist: dynaconf
|
|
15
|
+
Requires-Dist: dynaconf<4,>=3.2
|
|
16
16
|
Description-Content-Type: text/markdown
|
|
17
17
|
|
|
18
18
|
# influxdata-plugin-utils
|
|
@@ -36,7 +36,7 @@ pip install -e influxdata-plugin-utils
|
|
|
36
36
|
| Module | What it provides |
|
|
37
37
|
|-----------------|-----------------------------------------------------------------------------------------------------------------------------|
|
|
38
38
|
| `config` | `load_plugin_config(args, validators)` (dynaconf-backed), `resolve_plugin_dir()`, `resolve_path()`, re-exported `Validator` |
|
|
39
|
-
| `introspection` | `get_table_names()`, `get_tag_names()`, `get_field_names()`, `query_window()`
|
|
39
|
+
| `introspection` | `get_table_names()`, `get_tag_names()`, `get_field_names()`, `query_window()` with optional `database=` |
|
|
40
40
|
| `parsing` | `parse_timedelta()`, `parse_timestamp_ns()`, `parse_int()`, `parse_bool()`, `parse_delimited_list()`, `parse_key_value()` |
|
|
41
41
|
| `cache` | `cached(influxdb3_local, key, producer, ttl_seconds=3600)` |
|
|
42
42
|
| `write` | `build_line()`, `build_line_typed()`, `add_field_with_type()`, `write_data()`, `BatchLines` |
|
|
@@ -82,9 +82,32 @@ lines = [
|
|
|
82
82
|
]
|
|
83
83
|
write_data(influxdb3_local, lines) # batched + retried by default
|
|
84
84
|
# write_data(influxdb3_local, lines, batch=False, retries=0) # opt out
|
|
85
|
+
# write_data(influxdb3_local, lines, database="other_db") # another database
|
|
86
|
+
# write_data(influxdb3_local, lines, no_sync=True) # write_sync API (3.8+)
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Cross-database queries
|
|
90
|
+
|
|
91
|
+
On InfluxDB versions that support processing-engine cross-database queries,
|
|
92
|
+
the introspection helpers accept `database=` and pass it through to
|
|
93
|
+
`influxdb3_local.query`.
|
|
94
|
+
Cached schema results are separated per database.
|
|
95
|
+
|
|
96
|
+
```python
|
|
97
|
+
from influxdata_plugin_utils.introspection import get_field_names, query_window
|
|
98
|
+
|
|
99
|
+
fields = get_field_names(influxdb3_local, "cpu", database="source_db")
|
|
100
|
+
rows = query_window(
|
|
101
|
+
influxdb3_local,
|
|
102
|
+
"cpu",
|
|
103
|
+
start=start,
|
|
104
|
+
end=end,
|
|
105
|
+
columns=fields,
|
|
106
|
+
database="source_db",
|
|
107
|
+
)
|
|
85
108
|
```
|
|
86
109
|
|
|
87
110
|
## License
|
|
88
111
|
|
|
89
112
|
Licensed under either of [Apache License 2.0](LICENSE-APACHE) or
|
|
90
|
-
[MIT license](LICENSE-MIT) at your option.
|
|
113
|
+
[MIT license](LICENSE-MIT) at your option.
|
|
@@ -19,7 +19,7 @@ pip install -e influxdata-plugin-utils
|
|
|
19
19
|
| Module | What it provides |
|
|
20
20
|
|-----------------|-----------------------------------------------------------------------------------------------------------------------------|
|
|
21
21
|
| `config` | `load_plugin_config(args, validators)` (dynaconf-backed), `resolve_plugin_dir()`, `resolve_path()`, re-exported `Validator` |
|
|
22
|
-
| `introspection` | `get_table_names()`, `get_tag_names()`, `get_field_names()`, `query_window()`
|
|
22
|
+
| `introspection` | `get_table_names()`, `get_tag_names()`, `get_field_names()`, `query_window()` with optional `database=` |
|
|
23
23
|
| `parsing` | `parse_timedelta()`, `parse_timestamp_ns()`, `parse_int()`, `parse_bool()`, `parse_delimited_list()`, `parse_key_value()` |
|
|
24
24
|
| `cache` | `cached(influxdb3_local, key, producer, ttl_seconds=3600)` |
|
|
25
25
|
| `write` | `build_line()`, `build_line_typed()`, `add_field_with_type()`, `write_data()`, `BatchLines` |
|
|
@@ -65,9 +65,32 @@ lines = [
|
|
|
65
65
|
]
|
|
66
66
|
write_data(influxdb3_local, lines) # batched + retried by default
|
|
67
67
|
# write_data(influxdb3_local, lines, batch=False, retries=0) # opt out
|
|
68
|
+
# write_data(influxdb3_local, lines, database="other_db") # another database
|
|
69
|
+
# write_data(influxdb3_local, lines, no_sync=True) # write_sync API (3.8+)
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Cross-database queries
|
|
73
|
+
|
|
74
|
+
On InfluxDB versions that support processing-engine cross-database queries,
|
|
75
|
+
the introspection helpers accept `database=` and pass it through to
|
|
76
|
+
`influxdb3_local.query`.
|
|
77
|
+
Cached schema results are separated per database.
|
|
78
|
+
|
|
79
|
+
```python
|
|
80
|
+
from influxdata_plugin_utils.introspection import get_field_names, query_window
|
|
81
|
+
|
|
82
|
+
fields = get_field_names(influxdb3_local, "cpu", database="source_db")
|
|
83
|
+
rows = query_window(
|
|
84
|
+
influxdb3_local,
|
|
85
|
+
"cpu",
|
|
86
|
+
start=start,
|
|
87
|
+
end=end,
|
|
88
|
+
columns=fields,
|
|
89
|
+
database="source_db",
|
|
90
|
+
)
|
|
68
91
|
```
|
|
69
92
|
|
|
70
93
|
## License
|
|
71
94
|
|
|
72
95
|
Licensed under either of [Apache License 2.0](LICENSE-APACHE) or
|
|
73
|
-
[MIT license](LICENSE-MIT) at your option.
|
|
96
|
+
[MIT license](LICENSE-MIT) at your option.
|
|
@@ -12,7 +12,7 @@ license = "MIT OR Apache-2.0"
|
|
|
12
12
|
license-files = ["LICENSE-MIT", "LICENSE-APACHE"]
|
|
13
13
|
authors = [{ name = "InfluxData" }]
|
|
14
14
|
keywords = ["influxdb", "influxdb3", "plugins"]
|
|
15
|
-
dependencies = ["dynaconf>=3.2"]
|
|
15
|
+
dependencies = ["dynaconf>=3.2,<4"]
|
|
16
16
|
classifiers = [
|
|
17
17
|
"Programming Language :: Python :: 3.11",
|
|
18
18
|
"Operating System :: OS Independent",
|
|
@@ -4,6 +4,11 @@ Loads a plugin's TOML config (resolved via the plugin directory), merges
|
|
|
4
4
|
environment variables and engine-supplied ``args``, and validates the result.
|
|
5
5
|
dynaconf is an implementation detail and must not leak into plugin code beyond
|
|
6
6
|
the re-exported ``Validator``.
|
|
7
|
+
|
|
8
|
+
All values are treated as literal data. dynaconf's ``@`` token substitution
|
|
9
|
+
(``@read_file``, ``@format``, ``@get``, ...) is disabled so that a value
|
|
10
|
+
beginning with ``@`` is never evaluated against the server's filesystem or
|
|
11
|
+
environment; see https://github.com/influxdata/influxdb3_plugins/issues/134.
|
|
7
12
|
"""
|
|
8
13
|
|
|
9
14
|
import os
|
|
@@ -104,8 +109,14 @@ def load_plugin_config(
|
|
|
104
109
|
with open(resolve_path(config_file_path), "rb") as config_file:
|
|
105
110
|
layers.update(tomllib.load(config_file))
|
|
106
111
|
|
|
107
|
-
# loaders=[] disables the DYNACONF_* env loader; env is read only via
|
|
108
|
-
|
|
112
|
+
# loaders=[] disables the DYNACONF_* env loader; env is read only via
|
|
113
|
+
# env_keys. AUTO_CAST_FOR_DYNACONF=False disables dynaconf's "@" token
|
|
114
|
+
# substitution (@read_file, @format, @jinja, @get, ... — ~30 tokens, each
|
|
115
|
+
# beginning with "@"). Without it, any string value that begins with "@" is
|
|
116
|
+
# evaluated instead of stored as data, so an untrusted value arriving in an
|
|
117
|
+
# HTTP request body could read the server's files or environment variables.
|
|
118
|
+
# See https://github.com/influxdata/influxdb3_plugins/issues/134.
|
|
119
|
+
settings = Dynaconf(loaders=[], AUTO_CAST_FOR_DYNACONF=False)
|
|
109
120
|
settings.update(layers)
|
|
110
121
|
if validators:
|
|
111
122
|
settings.validators.register(*validators)
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
Each helper takes ``influxdb3_local`` explicitly and may optionally use the
|
|
4
4
|
TTL cache. Queries mirror the patterns already used across the plugins.
|
|
5
|
+
Helpers accept an optional ``database`` argument for engines that support
|
|
6
|
+
cross-database plugin queries.
|
|
5
7
|
"""
|
|
6
8
|
|
|
7
9
|
from .cache import cached
|
|
@@ -22,13 +24,40 @@ def _quote_identifier(identifier: str) -> str:
|
|
|
22
24
|
return '"' + identifier.replace('"', '""') + '"'
|
|
23
25
|
|
|
24
26
|
|
|
27
|
+
def _query(
|
|
28
|
+
influxdb3_local,
|
|
29
|
+
query: str,
|
|
30
|
+
args: dict | None = None,
|
|
31
|
+
database: str | None = None,
|
|
32
|
+
):
|
|
33
|
+
"""Run a plugin query, preserving the old call shape when no database is set."""
|
|
34
|
+
if database is None:
|
|
35
|
+
if args is None:
|
|
36
|
+
return influxdb3_local.query(query)
|
|
37
|
+
return influxdb3_local.query(query, args)
|
|
38
|
+
if args is None:
|
|
39
|
+
return influxdb3_local.query(query, database=database)
|
|
40
|
+
return influxdb3_local.query(query, args, database=database)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def _cache_key(base: str, database: str | None) -> str:
|
|
44
|
+
"""Return a cache key, keeping existing default-database keys unchanged."""
|
|
45
|
+
if database is None:
|
|
46
|
+
return base
|
|
47
|
+
return f"{base}:database:{database}"
|
|
48
|
+
|
|
49
|
+
|
|
25
50
|
def get_table_names(
|
|
26
|
-
influxdb3_local,
|
|
51
|
+
influxdb3_local,
|
|
52
|
+
*,
|
|
53
|
+
database: str | None = None,
|
|
54
|
+
use_cache: bool = True,
|
|
55
|
+
ttl_seconds: int = 3600,
|
|
27
56
|
) -> list[str]:
|
|
28
57
|
"""Return base table names via ``SHOW TABLES``."""
|
|
29
58
|
|
|
30
59
|
def producer() -> list[str]:
|
|
31
|
-
rows = influxdb3_local
|
|
60
|
+
rows = _query(influxdb3_local, "SHOW TABLES", database=database)
|
|
32
61
|
return [
|
|
33
62
|
row["table_name"]
|
|
34
63
|
for row in rows
|
|
@@ -36,12 +65,22 @@ def get_table_names(
|
|
|
36
65
|
]
|
|
37
66
|
|
|
38
67
|
if use_cache:
|
|
39
|
-
return cached(
|
|
68
|
+
return cached(
|
|
69
|
+
influxdb3_local,
|
|
70
|
+
_cache_key("shared:tables", database),
|
|
71
|
+
producer,
|
|
72
|
+
ttl_seconds=ttl_seconds,
|
|
73
|
+
)
|
|
40
74
|
return producer()
|
|
41
75
|
|
|
42
76
|
|
|
43
77
|
def get_tag_names(
|
|
44
|
-
influxdb3_local,
|
|
78
|
+
influxdb3_local,
|
|
79
|
+
table: str,
|
|
80
|
+
*,
|
|
81
|
+
database: str | None = None,
|
|
82
|
+
use_cache: bool = True,
|
|
83
|
+
ttl_seconds: int = 3600,
|
|
45
84
|
) -> list[str]:
|
|
46
85
|
"""Return tag column names of a table (``Dictionary(Int32, Utf8)`` columns)."""
|
|
47
86
|
|
|
@@ -50,14 +89,20 @@ def get_tag_names(
|
|
|
50
89
|
"SELECT column_name FROM information_schema.columns "
|
|
51
90
|
"WHERE table_name = $table AND data_type = $data_type"
|
|
52
91
|
)
|
|
53
|
-
rows =
|
|
54
|
-
|
|
92
|
+
rows = _query(
|
|
93
|
+
influxdb3_local,
|
|
94
|
+
query,
|
|
95
|
+
{"table": table, "data_type": _TAG_DATA_TYPE},
|
|
96
|
+
database=database,
|
|
55
97
|
)
|
|
56
98
|
return [row["column_name"] for row in rows]
|
|
57
99
|
|
|
58
100
|
if use_cache:
|
|
59
101
|
return cached(
|
|
60
|
-
influxdb3_local,
|
|
102
|
+
influxdb3_local,
|
|
103
|
+
_cache_key(f"shared:tags:{table}", database),
|
|
104
|
+
producer,
|
|
105
|
+
ttl_seconds=ttl_seconds,
|
|
61
106
|
)
|
|
62
107
|
return producer()
|
|
63
108
|
|
|
@@ -67,6 +112,7 @@ def get_field_names(
|
|
|
67
112
|
table: str,
|
|
68
113
|
*,
|
|
69
114
|
numeric_only: bool = False,
|
|
115
|
+
database: str | None = None,
|
|
70
116
|
use_cache: bool = True,
|
|
71
117
|
ttl_seconds: int = 3600,
|
|
72
118
|
) -> list[str]:
|
|
@@ -80,7 +126,7 @@ def get_field_names(
|
|
|
80
126
|
"SELECT column_name, data_type FROM information_schema.columns "
|
|
81
127
|
"WHERE table_name = $table"
|
|
82
128
|
)
|
|
83
|
-
rows = influxdb3_local
|
|
129
|
+
rows = _query(influxdb3_local, query, {"table": table}, database=database)
|
|
84
130
|
names: list[str] = []
|
|
85
131
|
for row in rows:
|
|
86
132
|
name = row["column_name"]
|
|
@@ -93,7 +139,7 @@ def get_field_names(
|
|
|
93
139
|
return names
|
|
94
140
|
|
|
95
141
|
if use_cache:
|
|
96
|
-
key = f"shared:fields:{table}:{int(numeric_only)}"
|
|
142
|
+
key = _cache_key(f"shared:fields:{table}:{int(numeric_only)}", database)
|
|
97
143
|
return cached(influxdb3_local, key, producer, ttl_seconds=ttl_seconds)
|
|
98
144
|
return producer()
|
|
99
145
|
|
|
@@ -105,6 +151,7 @@ def query_window(
|
|
|
105
151
|
start,
|
|
106
152
|
end,
|
|
107
153
|
columns: list[str] | None = None,
|
|
154
|
+
database: str | None = None,
|
|
108
155
|
) -> list[dict]:
|
|
109
156
|
"""Run a basic ``time``-window query and return rows (``[]`` if none).
|
|
110
157
|
|
|
@@ -118,5 +165,10 @@ def query_window(
|
|
|
118
165
|
f"SELECT {selected} FROM {_quote_identifier(table)} "
|
|
119
166
|
"WHERE time >= $start AND time < $end ORDER BY time"
|
|
120
167
|
)
|
|
121
|
-
rows =
|
|
122
|
-
|
|
168
|
+
rows = _query(
|
|
169
|
+
influxdb3_local,
|
|
170
|
+
query,
|
|
171
|
+
{"start": start, "end": end},
|
|
172
|
+
database=database,
|
|
173
|
+
)
|
|
174
|
+
return rows or []
|
|
@@ -19,6 +19,8 @@ __all__ = [
|
|
|
19
19
|
|
|
20
20
|
_DURATION_RE = re.compile(r"^\s*(\d+)\s*([a-zA-Z]+)\s*$")
|
|
21
21
|
_DURATION_UNITS = {
|
|
22
|
+
"us": "microseconds",
|
|
23
|
+
"ms": "milliseconds",
|
|
22
24
|
"s": "seconds",
|
|
23
25
|
"min": "minutes",
|
|
24
26
|
"h": "hours",
|
|
@@ -33,7 +35,7 @@ _FALSE = {"false", "f", "0", "no", "off"}
|
|
|
33
35
|
|
|
34
36
|
|
|
35
37
|
def parse_timedelta(raw) -> timedelta:
|
|
36
|
-
"""Parse a duration like ``30s``, ``5min``, ``1h``, ``2d``, ``1w``."""
|
|
38
|
+
"""Parse a duration like ``500us``, ``100ms``, ``30s``, ``5min``, ``1h``, ``2d``, ``1w``."""
|
|
37
39
|
if isinstance(raw, timedelta):
|
|
38
40
|
return raw
|
|
39
41
|
match = _DURATION_RE.match(str(raw))
|
{influxdata_plugin_utils-0.1.0 → influxdata_plugin_utils-0.3.0}/src/influxdata_plugin_utils/write.py
RENAMED
|
@@ -9,6 +9,7 @@ write helpers operate on already-built line objects and need no class.
|
|
|
9
9
|
import math
|
|
10
10
|
import random
|
|
11
11
|
import time
|
|
12
|
+
from functools import partial
|
|
12
13
|
|
|
13
14
|
from .parsing import parse_bool
|
|
14
15
|
|
|
@@ -160,7 +161,8 @@ def write_data(
|
|
|
160
161
|
batch: bool = True,
|
|
161
162
|
retries: int = 3,
|
|
162
163
|
base_delay: float = 1.0,
|
|
163
|
-
no_sync: bool =
|
|
164
|
+
no_sync: bool | None = None,
|
|
165
|
+
database: str | None = None,
|
|
164
166
|
) -> None:
|
|
165
167
|
"""Write LineBuilder objects with optional batching and retry.
|
|
166
168
|
|
|
@@ -170,8 +172,17 @@ def write_data(
|
|
|
170
172
|
batch: Combine all lines into one payload via :class:`BatchLines`.
|
|
171
173
|
Set ``False`` to write each line individually.
|
|
172
174
|
retries: Number of extra attempts on failure (``0`` disables retry).
|
|
175
|
+
Effective only when ``no_sync`` is set: the default buffered
|
|
176
|
+
``write`` / ``write_to_db`` never raise at call time.
|
|
173
177
|
base_delay: Base seconds for exponential backoff with jitter.
|
|
174
|
-
no_sync:
|
|
178
|
+
no_sync: When set, writes go through ``write_sync`` /
|
|
179
|
+
``write_sync_to_db`` with this flag (requires InfluxDB 3.8+),
|
|
180
|
+
which write immediately and raise on failure. When ``None``
|
|
181
|
+
(default), the universally available ``write`` / ``write_to_db``
|
|
182
|
+
are used: they only queue lines that are flushed after plugin
|
|
183
|
+
execution completes, so failures are not reported to the caller.
|
|
184
|
+
database: Target database; when ``None``, writes to the trigger's
|
|
185
|
+
database.
|
|
175
186
|
"""
|
|
176
187
|
builders = [builder for builder in line_builders if builder is not None]
|
|
177
188
|
if not builders:
|
|
@@ -180,13 +191,23 @@ def write_data(
|
|
|
180
191
|
payloads = [BatchLines(builders)] if batch else builders
|
|
181
192
|
attempts = max(retries, 0) + 1
|
|
182
193
|
|
|
194
|
+
if no_sync is None:
|
|
195
|
+
if database is not None:
|
|
196
|
+
write_fn = partial(influxdb3_local.write_to_db, database)
|
|
197
|
+
else:
|
|
198
|
+
write_fn = influxdb3_local.write
|
|
199
|
+
elif database is not None:
|
|
200
|
+
write_fn = partial(influxdb3_local.write_sync_to_db, database, no_sync=no_sync)
|
|
201
|
+
else:
|
|
202
|
+
write_fn = partial(influxdb3_local.write_sync, no_sync=no_sync)
|
|
203
|
+
|
|
183
204
|
for payload in payloads:
|
|
184
205
|
for attempt in range(attempts):
|
|
185
206
|
try:
|
|
186
|
-
|
|
207
|
+
write_fn(payload)
|
|
187
208
|
break
|
|
188
209
|
except Exception:
|
|
189
210
|
if attempt == attempts - 1:
|
|
190
211
|
raise
|
|
191
212
|
delay = (2**attempt) * base_delay + random.uniform(0, base_delay)
|
|
192
|
-
time.sleep(delay)
|
|
213
|
+
time.sleep(delay)
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
# Changelog
|
|
2
|
-
|
|
3
|
-
All notable changes to this project are documented in this file.
|
|
4
|
-
|
|
5
|
-
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
-
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
-
|
|
8
|
-
## [Unreleased]
|
|
9
|
-
|
|
10
|
-
## [0.1.0] - 2026-07-08
|
|
11
|
-
|
|
12
|
-
### Added
|
|
13
|
-
|
|
14
|
-
- `config` — dynaconf-backed config loading (`load_plugin_config`), plugin
|
|
15
|
-
directory resolution (`resolve_plugin_dir`, `resolve_path`), re-exported
|
|
16
|
-
`Validator`.
|
|
17
|
-
- `introspection` — schema helpers (`get_table_names`, `get_tag_names`,
|
|
18
|
-
`get_field_names`) and `query_window`, with optional TTL caching.
|
|
19
|
-
- `parsing` — `parse_timedelta`, `parse_timestamp_ns`, `parse_int`,
|
|
20
|
-
`parse_bool`, `parse_delimited_list`, `parse_key_value`.
|
|
21
|
-
- `cache` — `cached` TTL wrapper over `influxdb3_local.cache`.
|
|
22
|
-
- `write` — `build_line`, `build_line_typed`, `add_field_with_type`,
|
|
23
|
-
`write_data` (batching + retry), `BatchLines`.
|
|
24
|
-
|
|
25
|
-
[Unreleased]: https://github.com/influxdata/influxdb3_plugins/compare/utils-v0.1.0...HEAD
|
|
26
|
-
[0.1.0]: https://github.com/influxdata/influxdb3_plugins/releases/tag/utils-v0.1.0
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{influxdata_plugin_utils-0.1.0 → influxdata_plugin_utils-0.3.0}/src/influxdata_plugin_utils/cache.py
RENAMED
|
File without changes
|
{influxdata_plugin_utils-0.1.0 → influxdata_plugin_utils-0.3.0}/src/influxdata_plugin_utils/py.typed
RENAMED
|
File without changes
|