onliest 0.0.2 → 0.1.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 231435f376731f8c8e9ea57de9c5fa72c93584f6
4
- data.tar.gz: fae174999ac03c89d9847efc9f26687cd1b9336a
3
+ metadata.gz: efb038a4ae13fe3e96144555528df22c58069f09
4
+ data.tar.gz: 253159af40687da8125e46543ffbdf28a95cb646
5
5
  SHA512:
6
- metadata.gz: 75b616b372f8431dbbebd7395fefb3c0ab8737672568f931585cb25e0d2ff7973d23ccd1cfb5d8610a9868bb80d107dc197d5a756d8a95189ab1784aee0c7b9d
7
- data.tar.gz: 7a55e1ee34960ce44e98dc0ce63c00a9cfd03462dd8b96b9c68ad1de3dede8da9619c6392acd92fd2d88a5eeaa11e4251826d032bb7acf0f09a08ccc018e6ffa
6
+ metadata.gz: a3ad14aebd918aabb5b046f4b769220ed41fa4f668371b84126e084ca6522d98f47d109adf0099af6a426610bdb99ba5b23f8f67e23e5e7b9d1a555e67160df2
7
+ data.tar.gz: 976cc81e29400a059d515b6406ceb17ce6d55a10463b839d1128ab1a21eb71325b92eb3895f6fd67fa855a352a250fed769427a8e191acb331c2bdaea504b137
@@ -0,0 +1,42 @@
1
+ require 'onliest'
2
+
3
+ class Onliest::Snowflake < Onliest
4
+ attr_reader :worker_number, :sequence
5
+
6
+ # This comes from twitter snowflake. I'm not
7
+ # sure how they arrived at this number.
8
+ # November 3, 2010 at 11:42:55
9
+ EPOCH = 1288834974657
10
+
11
+ def initialize(worker_number)
12
+ @worker_number = worker_number
13
+ @sequence = 0
14
+ @older_time = 0
15
+ super(fields: [{ bits: 1, generator: ->{ 0 } },
16
+ { bits: 41, generator: ->{ time } },
17
+ { bits: 10, generator: ->{ worker_number } },
18
+ { bits: 12, generator: ->{ sequence_nextval } }])
19
+ end
20
+
21
+ private
22
+
23
+ def sequence_nextval
24
+ i = @sequence
25
+ @sequence = @sequence.succ
26
+ i
27
+ end
28
+
29
+ def time
30
+ while (t = time_now) < @older_time
31
+ #puts @older_time
32
+ #puts t
33
+ sleep((@older_time - t) / 1000)
34
+ end
35
+ @older_time = t
36
+ t
37
+ end
38
+
39
+ def time_now
40
+ ((Time.now.to_f * 1000).to_i - EPOCH)
41
+ end
42
+ end
data/lib/onliest.rb CHANGED
@@ -24,23 +24,28 @@ class Onliest
24
24
  # +SecureRandom+. An object that implements +:random_number+
25
25
  # returning a random integer >= 0 and less than value provided as
26
26
  # the first argument.
27
- def initialize(rng = DEFAULT_RNG)
28
- @rng = rng
27
+ def initialize(rng: DEFAULT_RNG, fields: false)
28
+ @fields = fields ? fields : default_fields(rng)
29
29
  end
30
30
 
31
- # Return the unique 72-bit value
31
+ # Construct and return the unique value
32
32
  def value
33
- (some_time_bits << RANDOM_BITS) +
34
- some_random_bits
33
+ total_bits = 0
34
+ total_value = 0
35
+ @fields.reverse.each do |field|
36
+ bits = field.fetch(:bits)
37
+ field_value = Integer(field.fetch(:generator).call) & ((2**bits) - 1)
38
+ total_value += (field_value << total_bits)
39
+ total_bits += bits
40
+ end
41
+ total_value
35
42
  end
36
43
 
37
44
  private
38
45
 
39
- def some_random_bits
40
- @rng.random_number(RANDOM_BITMASK + 1)
41
- end
42
-
43
- def some_time_bits
44
- Time.now.to_i & TIME_BITMASK
46
+ def default_fields(rng)
47
+ [{ bits: TIME_BITS, generator: -> { Time.now.to_i } },
48
+ { bits: RANDOM_BITS,
49
+ generator: -> { rng.random_number(RANDOM_BITMASK + 1) } }]
45
50
  end
46
51
  end
@@ -1,8 +1,9 @@
1
- require 'minitest/autorun'
2
-
1
+ require_relative './test_setup'
3
2
  require 'onliest'
4
3
 
5
- class OnliestTest < Minitest::Unit::TestCase
4
+ # Tests for the dkjefault scheme
5
+
6
+ class OnliestDefaultTest < TestCase
6
7
  def test_generates_a_number
7
8
  assert_kind_of(Integer, Onliest.value)
8
9
  end
@@ -16,31 +17,25 @@ class OnliestTest < Minitest::Unit::TestCase
16
17
  fake_prng.expect(:random_number, value, [2**47])
17
18
  end
18
19
 
19
- def at(value)
20
- Time.stub(:now, Time.at(value)) do
21
- yield
22
- end
23
- end
24
-
25
20
  def test_with_a_time_and_a_prng
26
21
  at((2**25) + 1) do
27
22
  random_value = 2
28
- gen = Onliest.new(fake_prng(random_value))
29
- assert_equal(gen.value, (1 << 47) + random_value)
23
+ gen = Onliest.new(rng: fake_prng(random_value))
24
+ assert_equal((1 << 47) + random_value, gen.value)
30
25
  end
31
26
  end
32
27
 
33
28
  def test_the_littlest_onliest
34
29
  at(0) do
35
- gen = Onliest.new(fake_prng(0))
30
+ gen = Onliest.new(rng: fake_prng(0))
36
31
  assert_equal(gen.value, 0)
37
32
  end
38
33
  end
39
34
 
40
35
  def test_the_largest_onliest
41
36
  at(2**25 - 1) do
42
- gen = Onliest.new(fake_prng(2**47 - 1))
43
- assert_equal(gen.value, 2**72 - 1)
37
+ gen = Onliest.new(rng: fake_prng(2**47 - 1))
38
+ assert_equal(2**72 - 1, gen.value)
44
39
  end
45
40
  end
46
41
  end
@@ -0,0 +1,54 @@
1
+ require_relative './test_setup'
2
+ require 'onliest/snowflake'
3
+
4
+ class SnowflakeTests < TestCase
5
+ def worker_number
6
+ '13'
7
+ end
8
+
9
+ def generator
10
+ Onliest::Snowflake.new(worker_number)
11
+ end
12
+
13
+ def test_snowflake_sign_bit_is_zero
14
+ assert_equal(0, generator.value & (1 << 63))
15
+ end
16
+
17
+ def test_snowflake_time_with_millisecond_precision
18
+ at(1.1234 + (Onliest::Snowflake::EPOCH.to_f / 1000)) do
19
+ assert_equal(1123, generator.value >> 22)
20
+ end
21
+ end
22
+
23
+ def test_snowflake_worker_number
24
+ assert_equal(worker_number.to_i, (generator.value & (2**22 - 1)) >> 12)
25
+ end
26
+
27
+ def test_snowflake_sequence_starts_at_zero
28
+ assert_equal(0, generator.value & ((2**12 - 1)))
29
+ end
30
+
31
+ def test_snowflake_sequence_increments
32
+ at(Time.now.to_i) do
33
+ gen = generator
34
+ assert_equal(gen.value, gen.value - 1)
35
+ end
36
+ end
37
+
38
+ def test_snowflake_epoch_starts_at_1288834974_657
39
+ at(1288834974657.to_f / 1000) do
40
+ assert_equal(0, generator.value >> 22)
41
+ end
42
+ end
43
+
44
+ def test_time_always_goes_forward
45
+ gen = generator
46
+ times = [Onliest::Snowflake::EPOCH + 0.10,
47
+ Onliest::Snowflake::EPOCH,
48
+ Onliest::Snowflake::EPOCH + 0.11]
49
+
50
+ Time.stub(:now, ->{ times.shift } ) do
51
+ assert(gen.value < gen.value)
52
+ end
53
+ end
54
+ end
metadata CHANGED
@@ -1,37 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: onliest
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robert Church
8
8
  autorequire:
9
9
  bindir: bin
10
- cert_chain:
11
- - |
12
- -----BEGIN CERTIFICATE-----
13
- MIIDaDCCAlCgAwIBAgIBATANBgkqhkiG9w0BAQUFADA9MQ8wDQYDVQQDDAZjaHJj
14
- aHIxFTATBgoJkiaJk/IsZAEZFgVnbWFpbDETMBEGCgmSJomT8ixkARkWA2NvbTAe
15
- Fw0xNDExMTcwMzU0NDZaFw0xNTExMTcwMzU0NDZaMD0xDzANBgNVBAMMBmNocmNo
16
- cjEVMBMGCgmSJomT8ixkARkWBWdtYWlsMRMwEQYKCZImiZPyLGQBGRYDY29tMIIB
17
- IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxYcGTCEi6hbbKJf8NtH1UIGg
18
- OFlMQjzp/QgN4IQV8wJbePzkm9Zfy0I19u/0Q+WmepkpwGLwEb84yiInpHpYKhVW
19
- 7MQOekiS+JxfGgXfAUtUZLLeeCe+R5IO9mZx+8PmA+S/WWaZngGuJE9vAi0Cobr7
20
- dKpsSeavB/mkE0V0jGnaUc6rJeO8sB/nzOeJ9OqxgUUI4698POpGLknhq9of//Yx
21
- 51WwQul6sItx/AELZKEM/Zuu+nvMCYFU0oM0OHMYaN5EDERjLGVXAYBTyKuUq0js
22
- kAydz6hfkrTBw8Aa/2s7w12EFq5jTBPS8fhvTFdGbveoF8HZuYV0PNEnSbhRpQID
23
- AQABo3MwcTAJBgNVHRMEAjAAMAsGA1UdDwQEAwIEsDAdBgNVHQ4EFgQUQT0zqrtG
24
- cFXJ2o4qWOe8Rq2FsEEwGwYDVR0RBBQwEoEQY2hyY2hyQGdtYWlsLmNvbTAbBgNV
25
- HRIEFDASgRBjaHJjaHJAZ21haWwuY29tMA0GCSqGSIb3DQEBBQUAA4IBAQBRdlDl
26
- dXzKVcuK/w1EwgfPlI3BVMbSBGx9evofmH8pSWOV7Pqu3ZU9u91SGzMtMULVj+03
27
- SJRx2pS3sVfzTt+jPfIqQk37rfc9iYLPCwM5G5RypT3iAIM/V/rJv5+z9lYwE/76
28
- 8ZrYVUK9zx91u/xkFseEig5ZqCCZIiBGKleos2uruy+eG5On1w5ShGqIaoxQvCa0
29
- W6y4KVKgJJKunt/R+DNGrFnPFkd+gzWOyinOhQoVeHvyhslkA+ptgJSk2Q/KwTXO
30
- 3TLzfUddZ0/HMBNYO9OALcF70YnWb/usnr4lwVfhbJ+fcejAsp5Seurmhw7FeMoZ
31
- f4Rtc1iUIHYWfDpz
32
- -----END CERTIFICATE-----
33
- date: 2014-11-15 00:00:00.000000000 Z
34
- dependencies: []
10
+ cert_chain: []
11
+ date: 2015-04-05 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rake
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '10'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '10'
27
+ - !ruby/object:Gem::Dependency
28
+ name: minitest
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '5'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '5'
35
41
  description: Generate unique values with numeric locality.
36
42
  email: chrchr@gmail.com
37
43
  executables:
@@ -39,9 +45,11 @@ executables:
39
45
  extensions: []
40
46
  extra_rdoc_files: []
41
47
  files:
42
- - lib/onliest.rb
43
48
  - bin/onliest
44
- - test/test_onliest.rb
49
+ - lib/onliest.rb
50
+ - lib/onliest/snowflake.rb
51
+ - test/test_onliest_default.rb
52
+ - test/test_onliest_snowflake.rb
45
53
  homepage: https://github.com/chrchr/onliest
46
54
  licenses:
47
55
  - MIT
@@ -52,20 +60,20 @@ require_paths:
52
60
  - lib
53
61
  required_ruby_version: !ruby/object:Gem::Requirement
54
62
  requirements:
55
- - - '>='
63
+ - - ">="
56
64
  - !ruby/object:Gem::Version
57
65
  version: '0'
58
66
  required_rubygems_version: !ruby/object:Gem::Requirement
59
67
  requirements:
60
- - - '>='
68
+ - - ">="
61
69
  - !ruby/object:Gem::Version
62
70
  version: '0'
63
71
  requirements: []
64
72
  rubyforge_project:
65
- rubygems_version: 2.0.14
73
+ rubygems_version: 2.4.5
66
74
  signing_key:
67
75
  specification_version: 4
68
76
  summary: 'Onliest: generate unique values with numeric locality'
69
77
  test_files:
70
- - test/test_onliest.rb
71
- has_rdoc:
78
+ - test/test_onliest_default.rb
79
+ - test/test_onliest_snowflake.rb
checksums.yaml.gz.sig DELETED
Binary file
data.tar.gz.sig DELETED
@@ -1,4 +0,0 @@
1
- ����o�����0�%�.��I ���?�Ү}7��
2
- �<胧�H�8�;{�,p䰰N�s��k�?���L���A_6��>����6"���+]��۸����w�#�� �s$=��_ܪRNj8�M)���`O��
3
- 
4
- ������j�B�R\i$���vG�Ŀ�1�hL P�Ys}�*��{�|���F�Rv`�h�U�11D��6e�s%�r��U�9η�o��.�0f m�J��P��/�0�oQ��$�
metadata.gz.sig DELETED
@@ -1,2 +0,0 @@
1
- U�`@
2
- hг*��Fs>��