tkati-node-dedup 0.4.3__tar.gz → 0.4.4__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.
- {tkati_node_dedup-0.4.3/src/tkati_node_dedup.egg-info → tkati_node_dedup-0.4.4}/PKG-INFO +16 -6
- tkati_node_dedup-0.4.3/PKG-INFO → tkati_node_dedup-0.4.4/README.md +14 -16
- {tkati_node_dedup-0.4.3 → tkati_node_dedup-0.4.4}/pyproject.toml +2 -2
- {tkati_node_dedup-0.4.3 → tkati_node_dedup-0.4.4}/src/tkati_node_dedup/main.py +22 -10
- tkati_node_dedup-0.4.3/README.md → tkati_node_dedup-0.4.4/src/tkati_node_dedup.egg-info/PKG-INFO +26 -4
- {tkati_node_dedup-0.4.3 → tkati_node_dedup-0.4.4}/src/tkati_node_dedup.egg-info/requires.txt +1 -1
- {tkati_node_dedup-0.4.3 → tkati_node_dedup-0.4.4}/setup.cfg +0 -0
- {tkati_node_dedup-0.4.3 → tkati_node_dedup-0.4.4}/src/tkati_node_dedup/__init__.py +0 -0
- {tkati_node_dedup-0.4.3 → tkati_node_dedup-0.4.4}/src/tkati_node_dedup/__main__.py +0 -0
- {tkati_node_dedup-0.4.3 → tkati_node_dedup-0.4.4}/src/tkati_node_dedup/py.typed +0 -0
- {tkati_node_dedup-0.4.3 → tkati_node_dedup-0.4.4}/src/tkati_node_dedup/settings.py +0 -0
- {tkati_node_dedup-0.4.3 → tkati_node_dedup-0.4.4}/src/tkati_node_dedup/store.py +0 -0
- {tkati_node_dedup-0.4.3 → tkati_node_dedup-0.4.4}/src/tkati_node_dedup.egg-info/SOURCES.txt +0 -0
- {tkati_node_dedup-0.4.3 → tkati_node_dedup-0.4.4}/src/tkati_node_dedup.egg-info/dependency_links.txt +0 -0
- {tkati_node_dedup-0.4.3 → tkati_node_dedup-0.4.4}/src/tkati_node_dedup.egg-info/entry_points.txt +0 -0
- {tkati_node_dedup-0.4.3 → tkati_node_dedup-0.4.4}/src/tkati_node_dedup.egg-info/top_level.txt +0 -0
- {tkati_node_dedup-0.4.3 → tkati_node_dedup-0.4.4}/tests/test_node_dedup.py +0 -0
- {tkati_node_dedup-0.4.3 → tkati_node_dedup-0.4.4}/tests/test_store.py +0 -0
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tkati-node-dedup
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.4
|
|
4
4
|
Summary: Kafka-to-Kafka streaming node that deduplicates events by a configurable field within a rolling processing-time window
|
|
5
5
|
Requires-Python: >=3.13
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
7
|
-
Requires-Dist: tkati-core==0.4.
|
|
7
|
+
Requires-Dist: tkati-core==0.4.4
|
|
8
8
|
Requires-Dist: loguru>=0.7.0
|
|
9
9
|
Requires-Dist: pydantic-settings>=2.11.0
|
|
10
10
|
Requires-Dist: pyarrow>=21.0.0
|
|
@@ -85,24 +85,34 @@ Every 10 seconds the node logs where its wall clock went, using
|
|
|
85
85
|
|
|
86
86
|
```
|
|
87
87
|
dedup perf over 10s: 157000 rows in, 153880 out (3120 dropped), 157 iterations (0 input-starved)
|
|
88
|
-
dedup perf:
|
|
88
|
+
dedup perf: poll=4.43s (44%) parse=0.48s (5%) lookup=0.52s (5%) produce=3.96s (39%) write=0.21s (2%) commit=0.38s (4%)
|
|
89
89
|
```
|
|
90
90
|
|
|
91
91
|
`dropped` is the rows this node deduplicated away.
|
|
92
92
|
|
|
93
|
-
* `
|
|
93
|
+
* `poll` — fetching message batches from the broker. Mostly broker round trips,
|
|
94
|
+
but it also includes librdkafka handing each message to Python, which has a
|
|
95
|
+
floor of roughly 0.8 us/message no matter how fast the broker is
|
|
96
|
+
* `parse` — JSON-decoding those payloads into an Arrow table, and casting to
|
|
97
|
+
the internal schema
|
|
94
98
|
* `lookup` — encoding keys, resolving in-batch duplicates, querying the store
|
|
95
99
|
* `produce` — serializing and producing, including the blocking `flush`
|
|
96
100
|
* `write` — marking the surviving keys seen
|
|
97
101
|
* `commit` — the synchronous offset commit (and bucket cleanup, which is ~0
|
|
98
102
|
except once an hour when a bucket is destroyed)
|
|
99
103
|
|
|
104
|
+
`poll` and `parse` come from `tkati-core`'s consumer rather than from this
|
|
105
|
+
node, which splices them in from `CONSUMER_PHASES`. They are split apart
|
|
106
|
+
because their fixes are unrelated: a large `poll` points at batch sizing,
|
|
107
|
+
broker latency or an under-fed topic, while a large `parse` points at the JSON
|
|
108
|
+
decode and is what a faster wire format would address.
|
|
109
|
+
|
|
100
110
|
Percentages are of the interval, not of each other, so they **do not sum to
|
|
101
111
|
100** — the remainder is time in none of the named phases.
|
|
102
112
|
|
|
103
113
|
`input-starved` counts iterations where the node drained the topic and waited
|
|
104
|
-
out the batch timeout. Those iterations were not CPU-bound, and because `
|
|
105
|
-
blocks for the whole wait, a mostly-starved interval will show `
|
|
114
|
+
out the batch timeout. Those iterations were not CPU-bound, and because `poll`
|
|
115
|
+
blocks for the whole wait, a mostly-starved interval will show `poll` at close
|
|
106
116
|
to 100% and tells you nothing about whether the node can keep up.
|
|
107
117
|
|
|
108
118
|
`benchmarks/bench_store.py` A/B tests the store in isolation. It populates in
|
|
@@ -1,15 +1,3 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: tkati-node-dedup
|
|
3
|
-
Version: 0.4.3
|
|
4
|
-
Summary: Kafka-to-Kafka streaming node that deduplicates events by a configurable field within a rolling processing-time window
|
|
5
|
-
Requires-Python: >=3.13
|
|
6
|
-
Description-Content-Type: text/markdown
|
|
7
|
-
Requires-Dist: tkati-core==0.4.3
|
|
8
|
-
Requires-Dist: loguru>=0.7.0
|
|
9
|
-
Requires-Dist: pydantic-settings>=2.11.0
|
|
10
|
-
Requires-Dist: pyarrow>=21.0.0
|
|
11
|
-
Requires-Dist: rocksdict>=0.3.0
|
|
12
|
-
|
|
13
1
|
# tkati-node-dedup — streaming deduplication node
|
|
14
2
|
|
|
15
3
|
Reads batches from a Kafka input topic, drops events that are duplicates of an
|
|
@@ -85,24 +73,34 @@ Every 10 seconds the node logs where its wall clock went, using
|
|
|
85
73
|
|
|
86
74
|
```
|
|
87
75
|
dedup perf over 10s: 157000 rows in, 153880 out (3120 dropped), 157 iterations (0 input-starved)
|
|
88
|
-
dedup perf:
|
|
76
|
+
dedup perf: poll=4.43s (44%) parse=0.48s (5%) lookup=0.52s (5%) produce=3.96s (39%) write=0.21s (2%) commit=0.38s (4%)
|
|
89
77
|
```
|
|
90
78
|
|
|
91
79
|
`dropped` is the rows this node deduplicated away.
|
|
92
80
|
|
|
93
|
-
* `
|
|
81
|
+
* `poll` — fetching message batches from the broker. Mostly broker round trips,
|
|
82
|
+
but it also includes librdkafka handing each message to Python, which has a
|
|
83
|
+
floor of roughly 0.8 us/message no matter how fast the broker is
|
|
84
|
+
* `parse` — JSON-decoding those payloads into an Arrow table, and casting to
|
|
85
|
+
the internal schema
|
|
94
86
|
* `lookup` — encoding keys, resolving in-batch duplicates, querying the store
|
|
95
87
|
* `produce` — serializing and producing, including the blocking `flush`
|
|
96
88
|
* `write` — marking the surviving keys seen
|
|
97
89
|
* `commit` — the synchronous offset commit (and bucket cleanup, which is ~0
|
|
98
90
|
except once an hour when a bucket is destroyed)
|
|
99
91
|
|
|
92
|
+
`poll` and `parse` come from `tkati-core`'s consumer rather than from this
|
|
93
|
+
node, which splices them in from `CONSUMER_PHASES`. They are split apart
|
|
94
|
+
because their fixes are unrelated: a large `poll` points at batch sizing,
|
|
95
|
+
broker latency or an under-fed topic, while a large `parse` points at the JSON
|
|
96
|
+
decode and is what a faster wire format would address.
|
|
97
|
+
|
|
100
98
|
Percentages are of the interval, not of each other, so they **do not sum to
|
|
101
99
|
100** — the remainder is time in none of the named phases.
|
|
102
100
|
|
|
103
101
|
`input-starved` counts iterations where the node drained the topic and waited
|
|
104
|
-
out the batch timeout. Those iterations were not CPU-bound, and because `
|
|
105
|
-
blocks for the whole wait, a mostly-starved interval will show `
|
|
102
|
+
out the batch timeout. Those iterations were not CPU-bound, and because `poll`
|
|
103
|
+
blocks for the whole wait, a mostly-starved interval will show `poll` at close
|
|
106
104
|
to 100% and tells you nothing about whether the node can keep up.
|
|
107
105
|
|
|
108
106
|
`benchmarks/bench_store.py` A/B tests the store in isolation. It populates in
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "tkati-node-dedup"
|
|
3
|
-
version = "0.4.
|
|
3
|
+
version = "0.4.4"
|
|
4
4
|
description = "Kafka-to-Kafka streaming node that deduplicates events by a configurable field within a rolling processing-time window"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.13"
|
|
7
7
|
dependencies = [
|
|
8
|
-
"tkati-core==0.4.
|
|
8
|
+
"tkati-core==0.4.4",
|
|
9
9
|
"loguru>=0.7.0",
|
|
10
10
|
"pydantic-settings>=2.11.0",
|
|
11
11
|
"pyarrow>=21.0.0",
|
|
@@ -1,15 +1,23 @@
|
|
|
1
1
|
import pyarrow as pa
|
|
2
2
|
from loguru import logger
|
|
3
|
-
from tkati_core import
|
|
3
|
+
from tkati_core import (
|
|
4
|
+
CONSUMER_PHASES,
|
|
5
|
+
Consumer,
|
|
6
|
+
LoopStats,
|
|
7
|
+
Producer,
|
|
8
|
+
build_consumer,
|
|
9
|
+
build_producer,
|
|
10
|
+
)
|
|
4
11
|
|
|
5
12
|
from tkati_node_dedup.settings import AppSettings
|
|
6
13
|
from tkati_node_dedup.store import BucketedDedupStore
|
|
7
14
|
|
|
8
15
|
# Reported in this order, not sorted by duration: a stable field order is what
|
|
9
|
-
# makes two consecutive log lines comparable at a glance.
|
|
10
|
-
# than in tkati-core because these
|
|
11
|
-
# tkati-node-el, for instance, has no lookup or write phase.
|
|
12
|
-
|
|
16
|
+
# makes two consecutive log lines comparable at a glance. The tail lives here
|
|
17
|
+
# rather than in tkati-core because these four names are this node's pipeline —
|
|
18
|
+
# tkati-node-el, for instance, has no lookup or write phase. The head is spliced
|
|
19
|
+
# in from the consumer, which owns the names it times itself against.
|
|
20
|
+
_PHASES = (*CONSUMER_PHASES, "lookup", "produce", "write", "commit")
|
|
13
21
|
|
|
14
22
|
|
|
15
23
|
def _new_stats() -> LoopStats:
|
|
@@ -57,11 +65,15 @@ def run_one_iteration(
|
|
|
57
65
|
except Exception:
|
|
58
66
|
logger.exception("dedup store cleanup failed; will retry next iteration")
|
|
59
67
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
68
|
+
# No phase block here: the consumer splits its own time into `poll` and
|
|
69
|
+
# `parse`. Wrapping it in an umbrella phase as well would double-count that
|
|
70
|
+
# time, and the percentages are of the interval — they are meant to fall
|
|
71
|
+
# short of 100%, with the shortfall being genuinely unaccounted work.
|
|
72
|
+
batch = consumer.read_arrow(
|
|
73
|
+
num_messages=settings.input.consumer.batch_size,
|
|
74
|
+
timeout=settings.input.consumer.batch_timeout_sec,
|
|
75
|
+
stats=stats,
|
|
76
|
+
)
|
|
65
77
|
stats.iterations += 1
|
|
66
78
|
if batch is None:
|
|
67
79
|
stats.starved_iterations += 1
|
tkati_node_dedup-0.4.3/README.md → tkati_node_dedup-0.4.4/src/tkati_node_dedup.egg-info/PKG-INFO
RENAMED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: tkati-node-dedup
|
|
3
|
+
Version: 0.4.4
|
|
4
|
+
Summary: Kafka-to-Kafka streaming node that deduplicates events by a configurable field within a rolling processing-time window
|
|
5
|
+
Requires-Python: >=3.13
|
|
6
|
+
Description-Content-Type: text/markdown
|
|
7
|
+
Requires-Dist: tkati-core==0.4.4
|
|
8
|
+
Requires-Dist: loguru>=0.7.0
|
|
9
|
+
Requires-Dist: pydantic-settings>=2.11.0
|
|
10
|
+
Requires-Dist: pyarrow>=21.0.0
|
|
11
|
+
Requires-Dist: rocksdict>=0.3.0
|
|
12
|
+
|
|
1
13
|
# tkati-node-dedup — streaming deduplication node
|
|
2
14
|
|
|
3
15
|
Reads batches from a Kafka input topic, drops events that are duplicates of an
|
|
@@ -73,24 +85,34 @@ Every 10 seconds the node logs where its wall clock went, using
|
|
|
73
85
|
|
|
74
86
|
```
|
|
75
87
|
dedup perf over 10s: 157000 rows in, 153880 out (3120 dropped), 157 iterations (0 input-starved)
|
|
76
|
-
dedup perf:
|
|
88
|
+
dedup perf: poll=4.43s (44%) parse=0.48s (5%) lookup=0.52s (5%) produce=3.96s (39%) write=0.21s (2%) commit=0.38s (4%)
|
|
77
89
|
```
|
|
78
90
|
|
|
79
91
|
`dropped` is the rows this node deduplicated away.
|
|
80
92
|
|
|
81
|
-
* `
|
|
93
|
+
* `poll` — fetching message batches from the broker. Mostly broker round trips,
|
|
94
|
+
but it also includes librdkafka handing each message to Python, which has a
|
|
95
|
+
floor of roughly 0.8 us/message no matter how fast the broker is
|
|
96
|
+
* `parse` — JSON-decoding those payloads into an Arrow table, and casting to
|
|
97
|
+
the internal schema
|
|
82
98
|
* `lookup` — encoding keys, resolving in-batch duplicates, querying the store
|
|
83
99
|
* `produce` — serializing and producing, including the blocking `flush`
|
|
84
100
|
* `write` — marking the surviving keys seen
|
|
85
101
|
* `commit` — the synchronous offset commit (and bucket cleanup, which is ~0
|
|
86
102
|
except once an hour when a bucket is destroyed)
|
|
87
103
|
|
|
104
|
+
`poll` and `parse` come from `tkati-core`'s consumer rather than from this
|
|
105
|
+
node, which splices them in from `CONSUMER_PHASES`. They are split apart
|
|
106
|
+
because their fixes are unrelated: a large `poll` points at batch sizing,
|
|
107
|
+
broker latency or an under-fed topic, while a large `parse` points at the JSON
|
|
108
|
+
decode and is what a faster wire format would address.
|
|
109
|
+
|
|
88
110
|
Percentages are of the interval, not of each other, so they **do not sum to
|
|
89
111
|
100** — the remainder is time in none of the named phases.
|
|
90
112
|
|
|
91
113
|
`input-starved` counts iterations where the node drained the topic and waited
|
|
92
|
-
out the batch timeout. Those iterations were not CPU-bound, and because `
|
|
93
|
-
blocks for the whole wait, a mostly-starved interval will show `
|
|
114
|
+
out the batch timeout. Those iterations were not CPU-bound, and because `poll`
|
|
115
|
+
blocks for the whole wait, a mostly-starved interval will show `poll` at close
|
|
94
116
|
to 100% and tells you nothing about whether the node can keep up.
|
|
95
117
|
|
|
96
118
|
`benchmarks/bench_store.py` A/B tests the store in isolation. It populates in
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tkati_node_dedup-0.4.3 → tkati_node_dedup-0.4.4}/src/tkati_node_dedup.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{tkati_node_dedup-0.4.3 → tkati_node_dedup-0.4.4}/src/tkati_node_dedup.egg-info/entry_points.txt
RENAMED
|
File without changes
|
{tkati_node_dedup-0.4.3 → tkati_node_dedup-0.4.4}/src/tkati_node_dedup.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|