1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
// Copyright 2025 Synadia Communications Inc.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! NATS JetStream distributed counters.
//!
//! This crate provides support for distributed counters using NATS JetStream streams
//! configured with the `AllowMsgCounter` option.
//!
//! # Overview
//!
//! The counters module wraps JetStream streams configured with `AllowMsgCounter` to provide
//! distributed counters. Each subject in the stream represents a separate counter.
//!
//! Counters are tracked across multiple sources, allowing for aggregation and source history.
//! The module supports operations like incrementing/decrementing counters, loading current values,
//! and retrieving source contributions.
//!
//! ## Key Features
//!
//! - **Arbitrary Precision**: Uses `BigInt` for unlimited integer size
//! - **Source Tracking**: Track counter contributions from multiple streams
//! - **Batch Operations**: Efficiently fetch multiple counter values
//! - **Atomic Operations**: Server-side atomic increment/decrement operations
//!
//! ## Stream Requirements
//!
//! Streams must have the following configuration:
//! - `allow_message_counter: true` - Enables counter functionality
//! - `allow_direct: true` - Required for efficient counter reads
//!
//! # Quick Start
//!
//! ```no_run
//! use nats_counters::CounterExt;
//! use async_nats::jetstream::stream::Config;
//!
//! # async fn example() -> Result<(), Box<dyn std::error::Error>> {
//! // Connect to NATS and create JetStream context
//! let client = async_nats::connect("localhost:4222").await?;
//! let js = async_nats::jetstream::new(client);
//!
//! // Create a counter-enabled stream
//! let config = Config {
//! name: "COUNTERS".to_string(),
//! subjects: vec!["counters.>".to_string()],
//! allow_message_counter: true,
//! allow_direct: true,
//! ..Default::default()
//! };
//! js.create_stream(config).await?;
//!
//! // Get the counter
//! let counter = js.get_counter("COUNTERS").await?;
//!
//! // Increment a counter
//! let value = counter.add("counters.visits", 1).await?;
//! println!("Visits: {}", value);
//!
//! // Read current value
//! let current = counter.load("counters.visits").await?;
//! println!("Current visits: {}", current);
//! # Ok(())
//! # }
//! ```
//!
//! # Source Tracking
//!
//! When using stream sourcing, counters track contributions from each source stream:
//!
//! ```no_run
//! # async fn example(counter: &nats_counters::Counter) -> Result<(), Box<dyn std::error::Error>> {
//! // Get counter with source information
//! let entry = counter.get("counters.total").await?;
//! println!("Total: {}", entry.value);
//!
//! // Show breakdown by source
//! for (stream, subjects) in &entry.sources {
//! for (subject, value) in subjects {
//! println!(" {} contributed {} from {}", stream, value, subject);
//! }
//! }
//! # Ok(())
//! # }
use BigInt;
use HashMap;
pub use ;
/// Header key used to store source contributions in counter messages.
pub const COUNTER_SOURCES_HEADER: &str = "Nats-Counter-Sources";
/// Header key used to indicate counter increment values.
pub const COUNTER_INCREMENT_HEADER: &str = "Nats-Incr";
/// Map of source streams to their subject-value contributions.
pub type CounterSources = ;
/// Represents a counter's current state with full source history.
// Module for the extension trait
// Module for the counter implementation
// Re-export main types
pub use Counter;
pub use CounterExt;