snowflaked 0.1.0-arm-linux
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.
- checksums.yaml +7 -0
- data/LICENSE.txt +21 -0
- data/README.md +145 -0
- data/lib/snowflaked/3.2/snowflaked.so +0 -0
- data/lib/snowflaked/3.3/snowflaked.so +0 -0
- data/lib/snowflaked/3.4/snowflaked.so +0 -0
- data/lib/snowflaked/4.0/snowflaked.so +0 -0
- data/lib/snowflaked/adapter_extension.rb +21 -0
- data/lib/snowflaked/model_extensions.rb +38 -0
- data/lib/snowflaked/railtie.rb +51 -0
- data/lib/snowflaked/schema_definitions.rb +21 -0
- data/lib/snowflaked/type/snowflake.rb +11 -0
- data/lib/snowflaked/version.rb +5 -0
- data/lib/snowflaked.rb +99 -0
- metadata +64 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 14eb8968868a8051dfc3313232f968989087ee8f908428b282e002234647d67e
|
|
4
|
+
data.tar.gz: d92aad6d491b3b712f080c222dd17dab58047453b1b07f4d4b7e929720c5c34d
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 6b990c8f71fd27ea7fc9dcbe77c4858788c5889085eca073183b14cf1a41b5b262040db476f6443a5e80fe6ce63f67b24aabf7dc76e7961f4497d0b5c80bd0da
|
|
7
|
+
data.tar.gz: 2fc7147b88f60b972ce369d9dd3387dc5863c4add3029a5d25b78e3ff2eee0036204f0677f05d4618e0185126ba75902095b3eed5c3b608f5908f524921103f4
|
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Luiz Eduardo Kowalski
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
# Snowflaked
|
|
2
|
+
|
|
3
|
+
A high-performance, thread-safe Snowflake ID generator for Ruby, powered by Rust.
|
|
4
|
+
|
|
5
|
+
Snowflake IDs are 64-bit unique identifiers that encode a timestamp, machine ID, and sequence number. They're time-sortable (IDs created later are always larger), making them ideal for distributed systems where you need unique IDs without coordination between machines. Unlike UUIDs, Snowflake IDs are smaller, sortable, and index-friendly for databases.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
Add to your Gemfile:
|
|
10
|
+
|
|
11
|
+
```ruby
|
|
12
|
+
gem "snowflaked"
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Quick Start
|
|
16
|
+
|
|
17
|
+
```ruby
|
|
18
|
+
id = Snowflaked.id
|
|
19
|
+
# => 7193489234823847936
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Rails Integration
|
|
23
|
+
|
|
24
|
+
All models automatically generate a Snowflake ID for the `:id` attribute:
|
|
25
|
+
|
|
26
|
+
```ruby
|
|
27
|
+
class User < ApplicationRecord
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
User.create!
|
|
31
|
+
# => #<User id: 7193489234823847936>
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
You can also define additional Snowflake columns in migrations:
|
|
35
|
+
|
|
36
|
+
```ruby
|
|
37
|
+
class CreateUsers < ActiveRecord::Migration[8.1]
|
|
38
|
+
def change
|
|
39
|
+
create_table :users do |t|
|
|
40
|
+
t.snowflake :external_id
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
If you want to generate Snowflake IDs for additional columns, you can do so by using the `snowflake_id` method, without having to migrate the table:
|
|
47
|
+
|
|
48
|
+
```ruby
|
|
49
|
+
class User < ApplicationRecord
|
|
50
|
+
snowflake_id :external_id
|
|
51
|
+
end
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
It is also possible to disable automatic `:id` generation by passing `id: false` to the `snowflake_id` method:
|
|
55
|
+
|
|
56
|
+
```ruby
|
|
57
|
+
class Post < ApplicationRecord
|
|
58
|
+
snowflake_id id: false
|
|
59
|
+
end
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Or generate Snowflake IDs for other columns but not `:id`:
|
|
63
|
+
|
|
64
|
+
```ruby
|
|
65
|
+
class Post < ApplicationRecord
|
|
66
|
+
snowflake_id :external_id, id: false
|
|
67
|
+
end
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Configuration
|
|
71
|
+
|
|
72
|
+
```ruby
|
|
73
|
+
Snowflaked.configure do |config|
|
|
74
|
+
config.machine_id = 42
|
|
75
|
+
config.epoch = Time.utc(2020, 1, 1)
|
|
76
|
+
end
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Machine ID Resolution
|
|
80
|
+
|
|
81
|
+
If `machine_id` is not explicitly configured, it resolves in this order:
|
|
82
|
+
|
|
83
|
+
1. `SNOWFLAKED_MACHINE_ID` environment variable
|
|
84
|
+
2. `MACHINE_ID` environment variable
|
|
85
|
+
3. Auto-detected using the following formula: `(hostname.hash ^ pid) % 1024`
|
|
86
|
+
|
|
87
|
+
For Kubernetes deployments, you can set the machine ID using an environment variable:
|
|
88
|
+
|
|
89
|
+
```yaml
|
|
90
|
+
env:
|
|
91
|
+
- name: SNOWFLAKED_MACHINE_ID
|
|
92
|
+
valueFrom:
|
|
93
|
+
fieldRef:
|
|
94
|
+
fieldPath: metadata.name
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Or use a StatefulSet ordinal for guaranteed unique values:
|
|
98
|
+
|
|
99
|
+
```yaml
|
|
100
|
+
env:
|
|
101
|
+
- name: SNOWFLAKED_MACHINE_ID
|
|
102
|
+
valueFrom:
|
|
103
|
+
fieldRef:
|
|
104
|
+
fieldPath: metadata.annotations['apps.kubernetes.io/pod-index']
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## API Reference
|
|
108
|
+
|
|
109
|
+
```ruby
|
|
110
|
+
id = Snowflaked.id
|
|
111
|
+
|
|
112
|
+
Snowflaked.parse(id)
|
|
113
|
+
# => {timestamp_ms: 1735123456789, machine_id: 42, sequence: 0}
|
|
114
|
+
|
|
115
|
+
Snowflaked.timestamp(id)
|
|
116
|
+
# => 2024-12-25 12:34:56 +0000
|
|
117
|
+
|
|
118
|
+
Snowflaked.timestamp_ms(id)
|
|
119
|
+
# => 1735123456789
|
|
120
|
+
|
|
121
|
+
Snowflaked.sequence(id)
|
|
122
|
+
# => 0
|
|
123
|
+
|
|
124
|
+
Snowflaked.machine_id(id)
|
|
125
|
+
# => 42
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Requirements
|
|
129
|
+
|
|
130
|
+
- Ruby >= 3.2
|
|
131
|
+
- rustc >= 1.81.0
|
|
132
|
+
- cargo >= 1.81.0
|
|
133
|
+
- Mise
|
|
134
|
+
|
|
135
|
+
## Development
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
mise install
|
|
139
|
+
bundle install
|
|
140
|
+
bundle exec rake
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## License
|
|
144
|
+
|
|
145
|
+
MIT
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Snowflaked
|
|
4
|
+
module AdapterExtension
|
|
5
|
+
SNOWFLAKE_TYPE = { name: "bigint" }.freeze
|
|
6
|
+
|
|
7
|
+
def native_database_types
|
|
8
|
+
super.merge(snowflake: SNOWFLAKE_TYPE)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
module ClassMethods
|
|
12
|
+
def native_database_types
|
|
13
|
+
super.merge(snowflake: SNOWFLAKE_TYPE)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def self.prepended(base)
|
|
18
|
+
base.singleton_class.prepend(ClassMethods)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Snowflaked
|
|
4
|
+
module ModelExtensions
|
|
5
|
+
extend ActiveSupport::Concern
|
|
6
|
+
|
|
7
|
+
included do
|
|
8
|
+
class_attribute :_snowflake_attributes, instance_writer: false, default: [:id] # rubocop:disable ThreadSafety/ClassAndModuleAttributes -- false positive
|
|
9
|
+
before_validation :_generate_snowflake_ids, on: :create
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
class_methods do
|
|
13
|
+
def snowflake_id(*attributes, id: true)
|
|
14
|
+
attrs = attributes.map(&:to_sym)
|
|
15
|
+
attrs |= [:id] if id
|
|
16
|
+
self._snowflake_attributes = attrs
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def _snowflake_columns_from_comments
|
|
20
|
+
return [] unless table_exists?
|
|
21
|
+
|
|
22
|
+
columns.select { |c| c.comment == Snowflaked::SchemaDefinitions::COMMENT }.map { |c| c.name.to_sym }
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
|
|
28
|
+
def _generate_snowflake_ids
|
|
29
|
+
attributes_to_generate = self.class._snowflake_attributes | self.class._snowflake_columns_from_comments
|
|
30
|
+
|
|
31
|
+
attributes_to_generate.each do |attribute|
|
|
32
|
+
next if self[attribute].present?
|
|
33
|
+
|
|
34
|
+
self[attribute] = Snowflaked.id
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rails/railtie"
|
|
4
|
+
|
|
5
|
+
module Snowflaked
|
|
6
|
+
class Railtie < Rails::Railtie
|
|
7
|
+
initializer "snowflaked.register_type", after: "active_record.initialize_database" do
|
|
8
|
+
ActiveSupport.on_load(:active_record) do
|
|
9
|
+
require "snowflaked/type/snowflake"
|
|
10
|
+
ActiveRecord::Type.register(:snowflake, Snowflaked::Type::Snowflake)
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
initializer "snowflaked.extend_adapters", after: "active_record.initialize_database" do
|
|
15
|
+
ActiveSupport.on_load(:active_record) do
|
|
16
|
+
require "snowflaked/adapter_extension"
|
|
17
|
+
|
|
18
|
+
adapters = %w[
|
|
19
|
+
PostgreSQLAdapter
|
|
20
|
+
Mysql2Adapter
|
|
21
|
+
TrilogyAdapter
|
|
22
|
+
SQLite3Adapter
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
adapters.each do |adapter_name|
|
|
26
|
+
next unless ActiveRecord::ConnectionAdapters.const_defined?(adapter_name)
|
|
27
|
+
|
|
28
|
+
ActiveRecord::ConnectionAdapters.const_get(adapter_name).prepend(
|
|
29
|
+
Snowflaked::AdapterExtension
|
|
30
|
+
)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
initializer "snowflaked.schema_definitions", after: "active_record.initialize_database" do
|
|
36
|
+
ActiveSupport.on_load(:active_record) do
|
|
37
|
+
require "snowflaked/schema_definitions"
|
|
38
|
+
|
|
39
|
+
ActiveRecord::ConnectionAdapters::TableDefinition.include(Snowflaked::SchemaDefinitions::TableDefinition)
|
|
40
|
+
ActiveRecord::ConnectionAdapters::Table.include(Snowflaked::SchemaDefinitions::Table)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
initializer "snowflaked.model_extensions", after: "active_record.initialize_database" do
|
|
45
|
+
ActiveSupport.on_load(:active_record) do
|
|
46
|
+
require "snowflaked/model_extensions"
|
|
47
|
+
ActiveRecord::Base.include(Snowflaked::ModelExtensions)
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Snowflaked
|
|
4
|
+
module SchemaDefinitions
|
|
5
|
+
COMMENT = "snowflaked"
|
|
6
|
+
|
|
7
|
+
module TableDefinition
|
|
8
|
+
def snowflake(name, **options)
|
|
9
|
+
options[:comment] = Snowflaked::SchemaDefinitions::COMMENT
|
|
10
|
+
column(name, :snowflake, **options)
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
module Table
|
|
15
|
+
def snowflake(name, **options)
|
|
16
|
+
options[:comment] = Snowflaked::SchemaDefinitions::COMMENT
|
|
17
|
+
column(name, :snowflake, **options)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
data/lib/snowflaked.rb
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "snowflaked/version"
|
|
4
|
+
require_relative "snowflaked/snowflaked"
|
|
5
|
+
require "socket"
|
|
6
|
+
|
|
7
|
+
require_relative "snowflaked/railtie" if defined?(Rails::Railtie)
|
|
8
|
+
|
|
9
|
+
module Snowflaked
|
|
10
|
+
MAX_MACHINE_ID = 1023
|
|
11
|
+
|
|
12
|
+
class Error < StandardError; end
|
|
13
|
+
class ConfigurationError < Error; end
|
|
14
|
+
|
|
15
|
+
class Configuration
|
|
16
|
+
attr_accessor :machine_id, :epoch
|
|
17
|
+
|
|
18
|
+
def initialize
|
|
19
|
+
@machine_id = nil
|
|
20
|
+
@epoch = nil
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def machine_id_value
|
|
24
|
+
id = @machine_id || default_machine_id
|
|
25
|
+
id % (MAX_MACHINE_ID + 1)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def epoch_ms
|
|
29
|
+
return nil unless @epoch
|
|
30
|
+
|
|
31
|
+
(@epoch.to_f * 1000).to_i
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
private
|
|
35
|
+
|
|
36
|
+
def default_machine_id
|
|
37
|
+
env_machine_id || hostname_pid_hash
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def env_machine_id
|
|
41
|
+
id = ENV["SNOWFLAKED_MACHINE_ID"] || ENV.fetch("MACHINE_ID", nil)
|
|
42
|
+
id&.to_i
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def hostname_pid_hash
|
|
46
|
+
(Socket.gethostname.hash ^ Process.pid) % (MAX_MACHINE_ID + 1)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
class << self
|
|
51
|
+
def configuration
|
|
52
|
+
@configuration ||= Configuration.new # rubocop:disable ThreadSafety/ClassInstanceVariable -- not changed after initialization
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def configure
|
|
56
|
+
yield(configuration) if block_given?
|
|
57
|
+
|
|
58
|
+
ensure_initialized!
|
|
59
|
+
configuration
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def id
|
|
63
|
+
ensure_initialized!
|
|
64
|
+
Native.generate
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def parse(id)
|
|
68
|
+
ensure_initialized!
|
|
69
|
+
Native.parse(id)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def timestamp(id)
|
|
73
|
+
time_ms = Native.timestamp_ms(id)
|
|
74
|
+
Time.at(time_ms / 1000, (time_ms % 1000) * 1000, :usec)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def machine_id(id)
|
|
78
|
+
ensure_initialized!
|
|
79
|
+
Native.machine_id(id)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def timestamp_ms(id)
|
|
83
|
+
Native.timestamp_ms(id)
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def sequence(id)
|
|
87
|
+
Native.sequence(id)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
private
|
|
91
|
+
|
|
92
|
+
def ensure_initialized!
|
|
93
|
+
return if Native.initialized?
|
|
94
|
+
|
|
95
|
+
config = configuration
|
|
96
|
+
Native.init_generator(config.machine_id_value, config.epoch_ms)
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: snowflaked
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: arm-linux
|
|
6
|
+
authors:
|
|
7
|
+
- Luiz Eduardo Kowalski
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2026-01-08 00:00:00.000000000 Z
|
|
12
|
+
dependencies: []
|
|
13
|
+
description: A Ruby gem for generating Twitter Snowflake IDs using a high-performance
|
|
14
|
+
Rust backend. Thread-safe with configurable machine ID and custom epoch support.
|
|
15
|
+
email:
|
|
16
|
+
executables: []
|
|
17
|
+
extensions: []
|
|
18
|
+
extra_rdoc_files: []
|
|
19
|
+
files:
|
|
20
|
+
- LICENSE.txt
|
|
21
|
+
- README.md
|
|
22
|
+
- lib/snowflaked.rb
|
|
23
|
+
- lib/snowflaked/3.2/snowflaked.so
|
|
24
|
+
- lib/snowflaked/3.3/snowflaked.so
|
|
25
|
+
- lib/snowflaked/3.4/snowflaked.so
|
|
26
|
+
- lib/snowflaked/4.0/snowflaked.so
|
|
27
|
+
- lib/snowflaked/adapter_extension.rb
|
|
28
|
+
- lib/snowflaked/model_extensions.rb
|
|
29
|
+
- lib/snowflaked/railtie.rb
|
|
30
|
+
- lib/snowflaked/schema_definitions.rb
|
|
31
|
+
- lib/snowflaked/type/snowflake.rb
|
|
32
|
+
- lib/snowflaked/version.rb
|
|
33
|
+
homepage: https://github.com/luizkowalski/snowflaked
|
|
34
|
+
licenses:
|
|
35
|
+
- MIT
|
|
36
|
+
metadata:
|
|
37
|
+
homepage_uri: https://github.com/luizkowalski/snowflaked
|
|
38
|
+
source_code_uri: https://github.com/luizkowalski/snowflaked
|
|
39
|
+
changelog_uri: https://github.com/luizkowalski/snowflaked/blob/main/CHANGES.md
|
|
40
|
+
bug_tracker_uri: https://github.com/luizkowalski/snowflaked/issues
|
|
41
|
+
rubygems_mfa_required: 'true'
|
|
42
|
+
post_install_message:
|
|
43
|
+
rdoc_options: []
|
|
44
|
+
require_paths:
|
|
45
|
+
- lib
|
|
46
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
47
|
+
requirements:
|
|
48
|
+
- - ">="
|
|
49
|
+
- !ruby/object:Gem::Version
|
|
50
|
+
version: '3.2'
|
|
51
|
+
- - "<"
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: 4.1.dev
|
|
54
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
55
|
+
requirements:
|
|
56
|
+
- - ">="
|
|
57
|
+
- !ruby/object:Gem::Version
|
|
58
|
+
version: '0'
|
|
59
|
+
requirements: []
|
|
60
|
+
rubygems_version: 3.5.23
|
|
61
|
+
signing_key:
|
|
62
|
+
specification_version: 4
|
|
63
|
+
summary: Fast Snowflake ID generator with Rust backend
|
|
64
|
+
test_files: []
|