redis_int64_autoincrement 1.0.1

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 2bbc26b02afa193c0e2947e4542f815dfc87deeb8c287f0e1247734b1da0e5bb
4
+ data.tar.gz: 89c192e8a7fe00c6f4fbda5820d994221fb43aab64c40f85e92aa0d45dc9b806
5
+ SHA512:
6
+ metadata.gz: cce355500385c72b4415a7c92476b0e06b19b4a82b32ee0085373464f3d2ec3f8cc3d24cc55065447990a895b1bcda5d1f85b1e7fbba4384c2e0fcf914014552
7
+ data.tar.gz: 52cf55f161551a6ae30ec71338acae604a956e41a0ebf272c1291aa625ce934b76c6cb00eefdea7c820440e75f320c31ee70f16b6994a1ac53afa0a7908549cc
data/CHANGELOG ADDED
@@ -0,0 +1,2 @@
1
+ 1.0.1 (2023-12-23)
2
+ Creted first version by AndrewTrumenov (chaky22222222@gmail.com).
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2023-2024 Andrew Chernuha
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,41 @@
1
+ = Int64 UUID (UInt64, UInt63) autoincremented via redis-server
2
+
3
+ Generates universally unique identifiers (UUID64) with unsigned Int64 (so it will be UInt63)
4
+ for use in distributed applications.
5
+ Based on:
6
+ 1) possibility autoincrement value in redis-server
7
+ 2) unix timestamps with microseconds
8
+ 3) expire key possibility in redis database.
9
+
10
+
11
+ == Generating UInt63 Ids
12
+
13
+ Call #generate to generate a new UUID64. The method returns a Int64 unique value.
14
+
15
+ For example in rails:
16
+
17
+ before_create do |record|
18
+ record.id ||= RedisInt64Autoincrement.generate(Rails.cache.redis || Redis.new(url: "redis://localhost:6379/0"))
19
+ end
20
+
21
+ == Why so hard?
22
+
23
+ We have an issue where the servers have different times on each server and during the time the server syncs the time we have a shift of a few seconds.
24
+ So this lib have +-50(UUID64_MAX_SECONDS_EXPIRE) seconds maximum for delta shift.
25
+
26
+ == Latest and Greatest
27
+
28
+ Source code and documentation hosted on Github: http://github.com/trumenov/redis_int64_autoincrement
29
+
30
+ To get UUID64 from source:
31
+
32
+ git clone git://github.com/trumenov/redis_int64_autoincrement.git
33
+
34
+
35
+ == License
36
+
37
+ This package is licensed under the MIT license and/or the Creative
38
+ Commons Attribution-ShareAlike.
39
+
40
+ :include: MIT-LICENSE
41
+
data/Rakefile ADDED
@@ -0,0 +1,41 @@
1
+ require 'rake/testtask'
2
+ #require 'rake/rdoctask'
3
+
4
+
5
+ spec = Gem::Specification.load(File.expand_path("redis_int64_autoincrement.gemspec", File.dirname(__FILE__)))
6
+
7
+ desc "Default Task"
8
+ task :default => :test
9
+
10
+
11
+ desc "Run all test cases"
12
+ Rake::TestTask.new do |test|
13
+ test.verbose = true
14
+ test.test_files = ['test/*.rb']
15
+ test.warning = true
16
+ end
17
+
18
+ # Create the documentation.
19
+ #Rake::RDocTask.new do |rdoc|
20
+ # rdoc.rdoc_files.include "README.rdoc", "lib/**/*.rb"
21
+ # rdoc.options = spec.rdoc_options
22
+ #end
23
+
24
+
25
+
26
+ desc "Push new release to rubyforge and git tag"
27
+ task :push do
28
+ sh "git push"
29
+ puts "Tagging version #{spec.version} .."
30
+ sh "git tag v#{spec.version}"
31
+ sh "git push --tag"
32
+ puts "Building and pushing gem .."
33
+ sh "gem build #{spec.name}.gemspec"
34
+ sh "gem push #{spec.name}-#{spec.version}.gem"
35
+ end
36
+
37
+ desc "Install #{spec.name} locally"
38
+ task :install do
39
+ sh "gem build #{spec.name}.gemspec"
40
+ sh "gem install #{spec.name}-#{spec.version}.gem"
41
+ end
@@ -0,0 +1,56 @@
1
+ class RedisInt64Autoincrement
2
+
3
+ # Why 50 seconds? Easy to debug and more than enouth for sync time delta shift.
4
+ # You can use 10 or 5 seconds - and all must working normal too.
5
+ # 50seconds was chosen by me without any explanation. Just took this value, i do not know why.
6
+ REDIS_KEY_TTL_SECONDS = 50
7
+
8
+ MAX_BUFFER_BITS_CNT = 63 # Do not use all 64 bits - in this case signed Int64 can be less than result uid
9
+ TIMESTAMP_BITS_CNT = 34.freeze # 34bits for 150+ years more than enougth
10
+ TIMESTAMP_MICROSECONDS_BITS_CNT = 20.freeze # 0..999_999 - require 20bits
11
+ INCREMENTED_ID_BITS_CNT = 7.freeze # 7bits for 0..127 INCREMENTED_UINT8_ID
12
+ SERVER_ID_BITS_CNT = 2.freeze
13
+ # So in result: 34 + 20 + 7 + 2 = 63bits(MAX_BUFFER_BITS_CNT).
14
+
15
+ TIMESTAMP_SECONDS_SHIFT_LEFT_CNT = (TIMESTAMP_MICROSECONDS_BITS_CNT + INCREMENTED_ID_BITS_CNT + SERVER_ID_BITS_CNT).freeze # 29 bits
16
+ TIMESTAMP_MICROSECONDS_SHIFT_LEFT_CNT = (INCREMENTED_ID_BITS_CNT + SERVER_ID_BITS_CNT).freeze # 9 bits
17
+ INCREMENTED_ID_MAX_VAL = ((1 << INCREMENTED_ID_BITS_CNT) - 1).freeze # 1111111b=127
18
+ UINT63_MAX_VAL = 9223372036854775808 # 2^63 = 9223372036854775808
19
+ LIB_FIRST_VAL = 914476352027817480 # First id was generated 23.12.2023 at ~17:30 (Kiev +2:00)
20
+
21
+ # Version number.
22
+ module Version
23
+ version = Gem::Specification.load(File.expand_path("../redis_int64_autoincrement.gemspec", File.dirname(__FILE__))).version.to_s.split(".").map { |i| i.to_i }
24
+ MAJOR = version[1]
25
+ MINOR = version[0]
26
+ PATCH = version[1]
27
+ STRING = "#{MAJOR}.#{MINOR}.#{PATCH}"
28
+ end
29
+
30
+ VERSION = Version::STRING
31
+
32
+ class << self
33
+ def generate(redis, namespace = 'default', options = {})
34
+ server_id = options[:server_id] || 0
35
+ time_redis = options[:time_redis] || redis
36
+ raise("Wrong server_id[#{server_id}]. Allow only 0..3 server_id") unless server_id.between?(0, 3)
37
+ time_arr = time_redis.time
38
+ raise("Wrong time type[#{time_arr.inspect}]") unless time_arr.count.eql?(2)
39
+ unix_seconds = time_arr.first.to_i
40
+ first_part = unix_seconds << TIMESTAMP_SECONDS_SHIFT_LEFT_CNT
41
+
42
+ microseconds = time_arr[1].to_i
43
+ raise("Wrong microseconds [#{microseconds}]") unless microseconds.between?(0, 999_999)
44
+ second_part = microseconds << TIMESTAMP_MICROSECONDS_SHIFT_LEFT_CNT
45
+
46
+ key = "ai64:#{namespace}:#{unix_seconds}:#{microseconds}"
47
+ incremented_val = redis.incrby(key, 1)
48
+ redis.expire(key, REDIS_KEY_TTL_SECONDS)
49
+ raise("Wrong incremented_val [#{incremented_val}]") unless incremented_val.between?(0, INCREMENTED_ID_MAX_VAL)
50
+ third_part = incremented_val << SERVER_ID_BITS_CNT
51
+ result = ((first_part | second_part) | third_part) | server_id
52
+ raise("Wrong result[#{result}]") unless result.between?(LIB_FIRST_VAL, UINT63_MAX_VAL)
53
+ result
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,20 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'redis_int64_autoincrement'
3
+ s.version = '1.0.1'
4
+ s.summary = "Int64 (UInt63) autoincrement via redis-servers"
5
+ s.description = <<-EOF
6
+ Int64 (UInt64, UInt63) autoincrement via redis-servers with timestamp in microseconds, autoincerent via redis key.
7
+ Support 1-5 redis servers in one system (1 - timestamp + 4 servers - autoincrementers).
8
+ EOF
9
+
10
+ s.authors << 'Trumenov' << 'Chaky'
11
+ s.email = 'chaky22222222@gmail.com'
12
+ s.homepage = 'http://github.com/trumenov/redis_int64_autoincrement'
13
+ s.license = 'MIT'
14
+
15
+ s.files = Dir['{bin,test,lib,docs}/**/*'] + ['README.rdoc', 'MIT-LICENSE', 'Rakefile', 'CHANGELOG', 'redis_int64_autoincrement.gemspec']
16
+
17
+ s.rdoc_options << '--main' << 'README.rdoc' << '--title' << 'Int64 redis autoincrementer' << '--line-numbers'
18
+ '--webcvs' << 'http://github.com/trumenov/redis_int64_autoincrement'
19
+ s.extra_rdoc_files = ['README.rdoc', 'MIT-LICENSE']
20
+ end
@@ -0,0 +1,19 @@
1
+ # encoding: UTF-8
2
+ # Author:: Andrew Chernuha chaky22222222@gmail.com
3
+ # License:: MIT and/or Creative Commons Attribution-ShareAlike
4
+
5
+ require 'test/unit'
6
+ require 'rubygems'
7
+ require 'redis_int64_autoincrement'
8
+ require "redis"
9
+
10
+ class TestRedisInt64Autoincrement < Test::Unit::TestCase
11
+
12
+ def test_check_generated_placed_in_target_region
13
+ redis = Redis.new(url: "redis://localhost:6379/0")
14
+ left_part = Time.now.to_i << (RedisInt64Autoincrement::MAX_BUFFER_BITS_CNT - RedisInt64Autoincrement::TIMESTAMP_BITS_CNT)
15
+ new_id = RedisInt64Autoincrement.generate(redis)
16
+ right_part = (Time.now.to_i + 1) << (RedisInt64Autoincrement::MAX_BUFFER_BITS_CNT - RedisInt64Autoincrement::TIMESTAMP_BITS_CNT)
17
+ assert new_id.between?(left_part, right_part)
18
+ end
19
+ end
metadata ADDED
@@ -0,0 +1,59 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: redis_int64_autoincrement
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Trumenov
8
+ - Chaky
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2023-12-23 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: |
15
+ Int64 (UInt64, UInt63) autoincrement via redis-servers with timestamp in microseconds, autoincerent via redis key.
16
+ Support 1-5 redis servers in one system (1 - timestamp + 4 servers - autoincrementers).
17
+ email: chaky22222222@gmail.com
18
+ executables: []
19
+ extensions: []
20
+ extra_rdoc_files:
21
+ - README.rdoc
22
+ - MIT-LICENSE
23
+ files:
24
+ - CHANGELOG
25
+ - MIT-LICENSE
26
+ - README.rdoc
27
+ - Rakefile
28
+ - lib/redis_int64_autoincrement.rb
29
+ - redis_int64_autoincrement.gemspec
30
+ - test/test_redis_int64_autoincrement.rb
31
+ homepage: http://github.com/trumenov/redis_int64_autoincrement
32
+ licenses:
33
+ - MIT
34
+ metadata: {}
35
+ post_install_message:
36
+ rdoc_options:
37
+ - "--main"
38
+ - README.rdoc
39
+ - "--title"
40
+ - Int64 redis autoincrementer
41
+ - "--line-numbers"
42
+ require_paths:
43
+ - lib
44
+ required_ruby_version: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ required_rubygems_version: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ requirements: []
55
+ rubygems_version: 3.3.26
56
+ signing_key:
57
+ specification_version: 4
58
+ summary: Int64 (UInt63) autoincrement via redis-servers
59
+ test_files: []