Skip to content

Commit

Permalink
v0.0.3: more examples in README, unified signature of make() and .max…
Browse files Browse the repository at this point in the history
…_value(), added --max-value to uuid05 utility
  • Loading branch information
strizhechenko committed Jun 25, 2023
1 parent 3b4d3e0 commit 5c17c94
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 11 deletions.
21 changes: 18 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,25 @@ pip install uuid05
``` python
from uuid05 import UUID05

# May be parametrized by workers: int, ttl: int, precision: int
# defaults are: workers=10, ttl=2 days, precision=1
# basic usage
uid = UUID05.make()
suffix: str = uid.as_b64()
object_name: str = f'autotest_object_{suffix}'

# .make() may be parametrized by workers: int, ttl: int, precision: int
# defaults are: workers=10, ttl=2 days, precision=1
uid: int = UUID05.make(workers=16, ttl=86400, precision=6) # 1419554951415
uid.as_b64() # 'AUqEXzNy'

# you may also want to just shorten your existing integer identifiers.
suffix: str = UUID05(123123123123).as_b64()
assert suffix == 'HKq1w7M'

# How to get maximum UUID value/length with given params?
max_value = UUID05.max_value(machines=16, ttl=86400, precision=6) # 1586399913600
len(str(max_value)) == 13
len(max_value.as_b64()) == 8 # AXFczaaA
len(f'autotest_object_{max_value.as_b64()}') == 23 # autotest_object_AXFczaaA
```

It can be also used as an utility from command-line:
Expand Down Expand Up @@ -83,7 +97,8 @@ Otherwise Redis, Memcached or another database with a single INCRementing counte
- If your objects are persistent - you'd better use [py-nanoid](https://github.com/puyuan/py-nanoid).
- If you need to generate multiple UIDs for multiple object really _quick_:
- generate one and reuse it, using a semantic or loop variable as a suffix;
- pass **precision** argument to `uuid05()`. It scales automatically with worker count, but if there are less than 16 workers, default is 1 which means 1 uuid per 0.1 second, usually it's enough.
- pass **precision** argument to `uuid05()`. It scales automatically with worker count,
but if there are less than 16 workers, default is 1 which means 1 uuid per 0.1 second, usually it's enough.
- `precision=3` argument will use milliseconds.
- `precision=6` for microseconds.
- if `precision=6` is not enough stop trying to make your identifier compact.
Expand Down
3 changes: 2 additions & 1 deletion cli/uuid05
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ def main():
parser.add_argument('-p', '--precision', type=int, help='Increase up to 6 if you create objects frequently.')
parser.add_argument('-b', '--base64', action='store_true', help='Use base64 to compact it event more')
parser.add_argument('-a', '--altchars', type=str, help='Alternative characters for b64encode')
parser.add_argument('-m', '--max-value', action='store_true', help='Return maximum possible value for given params')
args = parser.parse_args()
kwargs = {}
if args.workers:
Expand All @@ -20,7 +21,7 @@ def main():
kwargs['ttl'] = args.ttl
if args.precision:
kwargs['precision'] = args.precision
uid: UUID05 = UUID05.make(**kwargs)
uid: UUID05 = UUID05.max_value(**kwargs) if args.max_value else UUID05.make(**kwargs)
print((uid.as_b64(altchars=args.altchars.encode()) if args.altchars else uid.as_b64()) if args.base64 else uid)


Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

setup(
name='uuid05',
version='0.0.2',
version='0.0.3',
packages=['uuid05'],
url='https://github.com/strizhechenko/uuid05',
license='MIT',
Expand Down
16 changes: 10 additions & 6 deletions uuid05/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ def as_b64(self, *args, **kwargs) -> str:
If you're using uuid05 results as strings and want it to be more compact, and being integer or not doesn't matter
you may use this function to encode it to base64. You can transparently pass arguments of b64encode function here.
As there's not decoding assumed padding symbols are removed.
%timeit b64(uuid05()) - 2.87 µs ± 13.9 ns per loop @ 3.2GHz
%timeit UUID05.make().as_b64() - 2.87 µs ± 13.9 ns per loop @ 3.2 GHz
%timeit UUID05.make().as_b64() - 1.54 µs ± 5.25 ns per loop @ 3.8 GHz
%timeit UUID05(1333).as_b64() - 608 ns ± 2.68 ns per loop (with static UUID (skips generation))
>>> UUID05(34714).as_b64(altchars=b'_-')
'h5o'
>>> UUID05(11402098).as_b64(altchars=b'_-')
Expand All @@ -36,7 +38,9 @@ def make(cls, workers=10, ttl=2 * day, precision=0) -> 'UUID05':
Compact human-readable unique identifiers for temporary objects in small non-synchronizing distributed systems.
If your objects are persistent - you'd better use nanoid.
If you need to generate multiple UIDs for multiple object at once - generate one and use loop variable as suffix.
%timeit uuid05() - 2.1 µs ± 2.08 ns per loop @ 3.2GHz
%timeit UUID05.make() - 2.1 µs ± 2.08 ns per loop @ 3.2GHz
%timeit UUID05.make() - 849 ns ± 1.73 ns per loop @ 3.8GHz
%timeit UUID05.make() - 717 ns ± 1.76 ns per loop @ 4.7GHz
:arg workers - count of hosts in a system;
:arg ttl - how many seconds a temporary object lives in a system (maximum) before being deleted;
:arg precision (optional) - you can override (increase) a precision if objects are created frequently (max - 6);
Expand All @@ -53,10 +57,10 @@ def make(cls, workers=10, ttl=2 * day, precision=0) -> 'UUID05':
return UUID05(f'{run_id}{time_id}')

@classmethod
def uuid05_max_value(cls, machines=10, ttl=2 * day, precision=0) -> 'UUID05':
def max_value(cls, workers=10, ttl=2 * day, precision=0) -> 'UUID05':
""":returns - maximum value of an uuid05 with given params"""
precision = min(precision or int(machines ** (1 / 4)), 6)
run_id = machines - 1
precision = min(precision or int(workers ** (1 / 4)), 6)
run_id = workers - 1
time_id = ttl * ((10 ** precision) - 1)
return UUID05(f'{run_id}{time_id}')

Expand All @@ -67,6 +71,6 @@ def uuid05_max_value(cls, machines=10, ttl=2 * day, precision=0) -> 'UUID05':
for _workers in 2, 4, 10, 16, 32, 256:
worker_id = randint(0, _workers)
example_value = UUID05.make(_workers, _ttl)
max_value = UUID05.uuid05_max_value(_workers, _ttl)
max_value = UUID05.max_value(_workers, _ttl)
max_in_b64 = max_value.as_b64(altchars=b'-_')
print(f'| {_ttl} | {_workers} | {worker_id} | {example_value} | {max_value} | {max_in_b64} |')

0 comments on commit 5c17c94

Please sign in to comment.