-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
12 changed files
with
479 additions
and
18 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
from dataclasses import dataclass, replace | ||
from typing import Optional, List, Union | ||
from enum import Enum | ||
from .specs import TopicSpec, PartitionMap | ||
from humanfriendly import parse_timespan, parse_size | ||
|
||
|
||
class TopicMode(Enum): | ||
MIRROR = "mirror" | ||
ASSIGNED = "assigned" | ||
COMPUTED = "computed" | ||
|
||
|
||
class CompressionType(Enum): | ||
NONE = "none" | ||
GZIP = "gzip" | ||
SNAPPY = "snappy" | ||
LZ4 = "lz4" | ||
ANY = "any" | ||
ZSTD = "zstd" | ||
|
||
|
||
@dataclass(frozen=True) | ||
class NewTopic: | ||
mode: TopicMode = TopicMode.COMPUTED | ||
partitions: int = 1 | ||
replications: int = 1 | ||
ignore_rack: bool = False | ||
replica_assignment: Optional[List[PartitionMap]] = None | ||
retention_time: Optional[int] = None | ||
segment_size: Optional[int] = None | ||
compression_type: Optional[CompressionType] = None | ||
max_partition_size: Optional[int] = None | ||
system: bool = False | ||
|
||
@classmethod | ||
def create(cls) -> "NewTopic": | ||
"""Alternative constructor method""" | ||
return cls() | ||
|
||
def with_assignment(self, replica_assignment: List[PartitionMap]) -> "NewTopic": | ||
"""Set the assigned replica configuration""" | ||
return replace( | ||
self, mode=TopicMode.ASSIGNED, replica_assignment=replica_assignment | ||
) | ||
|
||
def as_mirror_topic(self) -> "NewTopic": | ||
"""Set as a mirror topic""" | ||
return replace(self, mode=TopicMode.MIRROR) | ||
|
||
def with_partitions(self, partitions: int) -> "NewTopic": | ||
"""Set the specified partitions""" | ||
if partitions < 0: | ||
raise ValueError("Partitions must be a positive integer") | ||
return replace(self, partitions=partitions) | ||
|
||
def with_replication(self, replication: int) -> "NewTopic": | ||
"""Set the specified replication factor""" | ||
if replication < 0: | ||
raise ValueError("Replication factor must be a positive integer") | ||
return replace(self, replications=replication) | ||
|
||
def with_ignore_rack(self, ignore: bool = True) -> "NewTopic": | ||
"""Set the rack ignore setting""" | ||
return replace(self, ignore_rack=ignore) | ||
|
||
def with_compression(self, compression: CompressionType) -> "NewTopic": | ||
"""Set the specified compression type""" | ||
return replace(self, compression_type=compression) | ||
|
||
def with_retention_time(self, retention_time: Union[str, int]) -> "NewTopic": | ||
"""Set the specified retention time""" | ||
|
||
if isinstance(retention_time, int): | ||
return replace(self, retention_time=retention_time) | ||
|
||
parsed_time = parse_timespan(retention_time) | ||
return replace(self, retention_time=parsed_time) | ||
|
||
def with_segment_size(self, size: Union[str, int]) -> "NewTopic": | ||
"""Set the specified segment size""" | ||
if isinstance(size, int): | ||
return replace(self, segment_size=size) | ||
|
||
parsed_size = parse_size(size, True) | ||
return replace(self, segment_size=parsed_size) | ||
|
||
def with_max_partition_size(self, size: Union[str, int]) -> "NewTopic": | ||
"""Set the specified max partition size""" | ||
if isinstance(size, int): | ||
return replace(self, max_partition_size=size) | ||
|
||
parsed_size = parse_size(size, True) | ||
return replace(self, max_partition_size=parsed_size) | ||
|
||
def as_system_topic(self, is_system: bool = True) -> "NewTopic": | ||
"""Set the topic as an internal system topic""" | ||
return replace(self, system=is_system) | ||
|
||
def build(self) -> TopicSpec: | ||
"""Build the TopicSpec based on the current configuration""" | ||
# Similar implementation to the original build method | ||
if self.mode == TopicMode.ASSIGNED and self.replica_assignment: | ||
spec = TopicSpec.new_assigned(self.replica_assignment) | ||
elif self.mode == TopicMode.MIRROR: | ||
spec = TopicSpec.new_mirror() | ||
else: | ||
spec = TopicSpec.new_computed( | ||
self.partitions, self.replications, self.ignore_rack | ||
) | ||
|
||
spec.set_system(self.system) | ||
|
||
if self.retention_time is not None: | ||
spec.set_retention_time(self.retention_time) | ||
|
||
if self.max_partition_size is not None or self.segment_size is not None: | ||
spec.set_storage(self.max_partition_size, self.segment_size) | ||
|
||
if self.compression_type is not None: | ||
spec.set_compression_type(self.compression_type.value) | ||
|
||
return spec |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
from typing import Optional, Union | ||
import re | ||
|
||
|
||
def parse_time_to_seconds(time_str: Union[str, int, None]) -> Optional[int]: | ||
""" | ||
Convert time string to seconds. | ||
Supports formats like: | ||
- '1d' (1 day) | ||
- '12h' (12 hours) | ||
- '30m' (30 minutes) | ||
- '3600' (direct seconds) | ||
- None | ||
""" | ||
if time_str is None: | ||
return None | ||
|
||
if isinstance(time_str, int): | ||
return time_str | ||
|
||
# Remove whitespace | ||
time_str = time_str.strip().lower() | ||
|
||
# Direct integer seconds | ||
if time_str.isdigit(): | ||
return int(time_str) | ||
|
||
# Pattern to match number + unit | ||
match = re.match(r"^(\d+)([dhms])$", time_str) | ||
if not match: | ||
raise ValueError(f"Invalid time format: {time_str}") | ||
|
||
value = int(match.group(1)) | ||
unit = match.group(2) | ||
|
||
multipliers = { | ||
"d": 86400, # days | ||
"h": 3600, # hours | ||
"m": 60, # minutes | ||
"s": 1, # seconds | ||
} | ||
|
||
return value * multipliers[unit] | ||
|
||
|
||
def parse_byte_size(size_str: Union[str, int, None]) -> Optional[int]: | ||
""" | ||
Convert byte size string to integer bytes. | ||
Supports formats like: | ||
- '1G' (1 Gigabyte) | ||
- '500M' (500 Megabytes) | ||
- '1024K' (1024 Kilobytes) | ||
- '1024' (direct bytes) | ||
- None | ||
""" | ||
if size_str is None: | ||
return None | ||
|
||
if isinstance(size_str, int): | ||
return size_str | ||
|
||
# Remove whitespace | ||
size_str = size_str.strip().upper() | ||
|
||
# Direct integer bytes | ||
if size_str.isdigit(): | ||
return int(size_str) | ||
|
||
# Pattern to match number + unit | ||
match = re.match(r"^(\d+)([KMGT])$", size_str) | ||
if not match: | ||
raise ValueError(f"Invalid size format: {size_str}") | ||
|
||
value = int(match.group(1)) | ||
unit = match.group(2) | ||
|
||
multipliers = { | ||
"K": 1024, # Kilobytes | ||
"M": 1024 * 1024, # Megabytes | ||
"G": 1024 * 1024 * 1024, # Gigabytes | ||
"T": 1024 * 1024 * 1024 * 1024, # Terabytes | ||
} | ||
|
||
return value * multipliers[unit] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,3 +7,4 @@ black==24.8.0 | |
semantic-version==2.10.0 | ||
setuptools-rust==1.10.1 | ||
toml==0.10.2 | ||
humanfriendly==10.0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.