API Reference
Twain
The central entry point for interacting with a TwainMQ installation.
A Twain instance represents a complete TwainMQ environment rooted at a
directory on disk. This directory contains all topics, configuration files,
and global metadata. Applications typically create one long-lived Twain
object and use it to manage topics, producers, consumers, and message
registrations.
Parameters
root_dir : str or Path Filesystem path to the TwainMQ root directory. This directory will hold all topic data, configuration, and state.
Message Classes
Dataclass-based messages must be registered with the Twain instance before
they can be produced or consumed. Registration assigns each message type a
stable numeric identifier used during encoding. All producers and consumers
created from the same Twain share this registry.
In rare cases where different topics require dataclasses with the same
message name but different schemas, separate Twain instances must be used.
(It is strongly recommended to avoid such naming collisions.)
Notes
- A
Twainobject is intended to be long-lived and reused across your application. - Global configuration (e.g. message type registry) is stored at the
Twainlevel and applies to all producers and consumers created from it. - Topics created through this instance are immediately available for producing and consuming messages.
Examples
Create a Twain instance pointing at a local directory:
tmq = Twain("C:/TwainMQ")
Create a new topic with 16-bit unsigned integer keys:
tmq.create_topic("hello_world", "u16")
Produce a message:
producer = tmq.producer("hello_world") producer.write_message(42, "Hello!")
Consume messages:
consumer = tmq.consumer("hello_world") msg = consumer.poll()
Source code in src/twainmq/core.py
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 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 | |
consumer(topic_name, start_from=None, group=None)
Create a consumer for the given topic.
Parameters
topic_name : str
The topic to consume from.
start_from : {"start", "now"}, optional
Initial read position when no committed offset exists. Defaults to
"start".
group : str or None, optional
Consumer-group identifier. If provided, the consumer joins the group and
participates in consensus-based partition assignment and commits.
Returns
TwainMQConsumer A consumer bound to the specified topic.
Source code in src/twainmq/core.py
209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 | |
create_topic(topic_name, key_type=None, partitions=1, message_types=None)
Create a new topic in this TwainMQ instance.
Parameters
topic_name : str
Name of the topic. Must contain only safe characters.
key_type : str, optional
Key encoding type. Defaults to "u16". Supported values are "u8",
"u16", "u32", "u64", or "charN" where N is the number of
characters.
partitions : int, optional
Number of partitions for the topic. Defaults to 1.
message_types : list of str, optional
Names of dataclass message types used by this topic. These do not need
to be registered yet; they are recorded in the topic configuration.
Raises
InvalidTopicNameError
If the topic name contains invalid characters.
InvalidKeyTypeError
If key_type is not recognised.
ValueError
If the topic already exists.
Source code in src/twainmq/core.py
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 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 | |
delete_topic(topic_name)
Delete a topic and all of its data.
This operation is irreversible. A confirmation prompt is shown to prevent accidental deletion.
Parameters
topic_name : str The name of the topic to delete.
Returns
None or TopicDeleteError Returns an error object if the user fails the confirmation prompt.
Source code in src/twainmq/core.py
168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 | |
list_topics()
List all topics in this TwainMQ instance.
Returns
list of str Names of all topics, excluding internal consumer‑group directories.
Source code in src/twainmq/core.py
251 252 253 254 255 256 257 258 259 260 | |
producer(topic_name)
Create a producer for the given topic.
Parameters
topic_name : str The topic to produce messages to.
Returns
TwainMQProducer A producer bound to the specified topic.
Source code in src/twainmq/core.py
193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 | |
register_msg_cls(message_cls)
Register a dataclass message type for use with this Twain instance.
Dataclass messages must be registered before they can be produced or consumed. Registration assigns the class a stable numeric identifier used during encoding and decoding.
Parameters
message_cls : type
A dataclass defining a message schema. The class name (or its
__message_type__ attribute, if present) is used as the message type
identifier.
Raises
KeyError If a message class with the same name is already registered.
Source code in src/twainmq/core.py
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | |
topic_exists(topic_name)
Check whether a topic exists in this TwainMQ instance.
Parameters
topic_name : str
Returns
bool True if the topic exists, False otherwise.
Source code in src/twainmq/core.py
236 237 238 239 240 241 242 243 244 245 246 247 248 249 | |
TwainMQProducer
Bases: TwainMQBase
A producer for writing messages to a TwainMQ topic.
Producers assign messages to partitions using a configurable partitioner and append them atomically to the topic's storage. Messages may be strings, bytes, or registered dataclass instances. Producers are lightweight and may be used directly or as context managers to ensure clean shutdown.
Source code in src/twainmq/producer.py
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 138 139 140 141 | |
__init__(twain, topic, partitioner=None)
Create a producer for a given topic.
Parameters
twain : Twain
The TwainMQ instance backing this producer.
topic : str
The topic to write messages to.
partitioner : callable, optional
A function mapping (key, n_partitions) to a partition index.
If omitted, a stable 64-bit hash partitioner is used.
Source code in src/twainmq/producer.py
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | |
write_message(key, message)
Write a message to the topic, assigning it to a partition based on the key.
Messages may be:
- str: stored as UTF-8 text,
- bytes: stored as raw binary,
- dataclass instances: encoded as JSON. Dataclasses must be registered with
the Twain instance via register_msg_cls() before use.
The key determines the target partition and the type is set on topic creating.
The message is appended atomically to the selected partition file.
Parameters
key : any Value used to select the partition. Must be compatible with the topic. message : str, bytes, or dataclass The message payload to write.
Raises
MessageTooLongError
If the encoded message exceeds MAX_MESSAGE_SIZE.
Source code in src/twainmq/producer.py
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 | |
TwainMQConsumer
Bases: TwainMQBase
A TwainMQ consumer.
Consumers may operate independently or as part of a consumer group. A standalone consumer can read messages but cannot commit progress. A consumer that belongs to a group (even a group of one) can commit offsets, allowing any consumer joining that group to resume from the last committed position.
The start_from parameter controls the initial read position only when:
- the consumer is not part of a group, or
- the group has no existing commit record.
Source code in src/twainmq/consumer.py
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 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 | |
__init__(twain, topic, start_from='start', group=None)
Create a consumer for a given topic.
Parameters
twain : Twain
The TwainMQ instance backing this consumer.
topic : str
The topic to consume from.
start_from : {"start", "now"}, optional
Initial read position when no committed offset exists. "start"
begins at offset 0; "now" begins at the current end of each
partition.
group : str or None, optional
The consumer-group identifier. If None, the consumer operates
independently and cannot commit offsets. If provided, the consumer
joins the group and participates in consensus-based partition
assignment and offset commits.
Source code in src/twainmq/consumer.py
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 | |
heartbeat()
Maintain membership in a consumer group and process group-management events.
This method must be called periodically when using consumer groups; otherwise the consumer may be considered inactive and be removed from the group.
Behaviour
- Processes any pending group-management messages (rebalance events, etc.).
- Automatically invoked at the start of
poll().
Source code in src/twainmq/consumer.py
192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 | |
poll()
Poll partitions in round-robin order and return the next available message.
The consumer maintains a list of assigned partitions. Each call polls them
starting from the partition after the one last successfully polled. The first
non-None message returned by a partition is yielded.
This call does not block.
Returns
message or None
The next available message, or None if all partitions return no data.
Source code in src/twainmq/consumer.py
210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 | |
poll_many(n=10)
Poll up to n messages and return them as a list.
This is a convenience wrapper around poll(). Polling stops early if
poll() returns None.
Parameters
n : int, optional Maximum number of messages to retrieve.
Returns
list
A list of messages, possibly shorter than n.
Source code in src/twainmq/consumer.py
235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 | |
trigger_rebal()
Initiate a consumer-group rebalance.
In TwainMQ, consumer-group membership is maintained through periodic consensus. Triggering a rebalance is lightweight and safe, and is typically done periodically to confirm that all consumers in the group are still active.
If all consumers respond within the rebalance window, the rebalance becomes a no-op and existing partition assignments remain unchanged.
Source code in src/twainmq/consumer.py
125 126 127 128 129 130 131 132 133 134 135 136 137 | |
TwainMQConsumerlet
Bases: TwainMQBase
A consumerlet is a simple single partition consumer. Usually you would not use a Consumerlet directly, rather use the Consumer container
Source code in src/twainmq/consumer.py
263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 | |
poll()
Polls for the next message without blocking. Returns None if no new message available.
Source code in src/twainmq/consumer.py
327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 | |