bunny 1.3.0 → 2.17.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.
Files changed (143) hide show
  1. checksums.yaml +5 -5
  2. data/.github/ISSUE_TEMPLATE.md +18 -0
  3. data/.gitignore +7 -1
  4. data/.rspec +1 -3
  5. data/.travis.yml +21 -14
  6. data/CONTRIBUTING.md +132 -0
  7. data/ChangeLog.md +887 -1
  8. data/Gemfile +13 -13
  9. data/LICENSE +1 -1
  10. data/README.md +46 -60
  11. data/Rakefile +54 -0
  12. data/bunny.gemspec +5 -11
  13. data/docker-compose.yml +28 -0
  14. data/docker/Dockerfile +24 -0
  15. data/docker/apt/preferences.d/erlang +3 -0
  16. data/docker/apt/sources.list.d/bintray.rabbitmq.list +2 -0
  17. data/docker/docker-entrypoint.sh +26 -0
  18. data/docker/rabbitmq.conf +29 -0
  19. data/examples/connection/automatic_recovery_with_basic_get.rb +1 -1
  20. data/examples/connection/automatic_recovery_with_client_named_queues.rb +1 -1
  21. data/examples/connection/automatic_recovery_with_multiple_consumers.rb +1 -1
  22. data/examples/connection/automatic_recovery_with_republishing.rb +1 -1
  23. data/examples/connection/automatic_recovery_with_server_named_queues.rb +1 -1
  24. data/examples/connection/channel_level_exception.rb +1 -9
  25. data/examples/connection/disabled_automatic_recovery.rb +1 -1
  26. data/examples/connection/heartbeat.rb +1 -1
  27. data/examples/consumers/high_and_low_priority.rb +1 -1
  28. data/examples/guides/extensions/alternate_exchange.rb +2 -0
  29. data/examples/guides/extensions/basic_nack.rb +1 -1
  30. data/examples/guides/extensions/dead_letter_exchange.rb +1 -1
  31. data/examples/guides/getting_started/hello_world.rb +2 -0
  32. data/examples/guides/getting_started/weathr.rb +2 -0
  33. data/examples/guides/queues/one_off_consumer.rb +2 -0
  34. data/examples/guides/queues/redeliveries.rb +4 -2
  35. data/lib/bunny.rb +8 -4
  36. data/lib/bunny/channel.rb +268 -153
  37. data/lib/bunny/channel_id_allocator.rb +6 -4
  38. data/lib/bunny/concurrent/continuation_queue.rb +34 -13
  39. data/lib/bunny/consumer_work_pool.rb +34 -6
  40. data/lib/bunny/cruby/socket.rb +48 -21
  41. data/lib/bunny/cruby/ssl_socket.rb +65 -4
  42. data/lib/bunny/exceptions.rb +25 -4
  43. data/lib/bunny/exchange.rb +24 -28
  44. data/lib/bunny/get_response.rb +1 -1
  45. data/lib/bunny/heartbeat_sender.rb +3 -2
  46. data/lib/bunny/jruby/socket.rb +23 -6
  47. data/lib/bunny/jruby/ssl_socket.rb +5 -0
  48. data/lib/bunny/queue.rb +31 -22
  49. data/lib/bunny/reader_loop.rb +31 -18
  50. data/lib/bunny/session.rb +448 -159
  51. data/lib/bunny/test_kit.rb +14 -0
  52. data/lib/bunny/timeout.rb +1 -12
  53. data/lib/bunny/transport.rb +205 -98
  54. data/lib/bunny/version.rb +1 -1
  55. data/repl +1 -1
  56. data/spec/config/enabled_plugins +1 -0
  57. data/spec/config/rabbitmq.conf +13 -0
  58. data/spec/higher_level_api/integration/basic_ack_spec.rb +175 -16
  59. data/spec/higher_level_api/integration/basic_cancel_spec.rb +77 -11
  60. data/spec/higher_level_api/integration/basic_consume_spec.rb +60 -55
  61. data/spec/higher_level_api/integration/basic_consume_with_objects_spec.rb +6 -6
  62. data/spec/higher_level_api/integration/basic_get_spec.rb +31 -7
  63. data/spec/higher_level_api/integration/basic_nack_spec.rb +22 -19
  64. data/spec/higher_level_api/integration/basic_publish_spec.rb +11 -100
  65. data/spec/higher_level_api/integration/basic_qos_spec.rb +32 -4
  66. data/spec/higher_level_api/integration/basic_reject_spec.rb +94 -16
  67. data/spec/higher_level_api/integration/basic_return_spec.rb +4 -4
  68. data/spec/higher_level_api/integration/channel_close_spec.rb +51 -10
  69. data/spec/higher_level_api/integration/channel_open_spec.rb +12 -12
  70. data/spec/higher_level_api/integration/connection_recovery_spec.rb +424 -221
  71. data/spec/higher_level_api/integration/connection_spec.rb +300 -126
  72. data/spec/higher_level_api/integration/connection_stop_spec.rb +31 -19
  73. data/spec/higher_level_api/integration/consumer_cancellation_notification_spec.rb +17 -17
  74. data/spec/higher_level_api/integration/dead_lettering_spec.rb +34 -11
  75. data/spec/higher_level_api/integration/exchange_bind_spec.rb +5 -5
  76. data/spec/higher_level_api/integration/exchange_declare_spec.rb +32 -31
  77. data/spec/higher_level_api/integration/exchange_delete_spec.rb +12 -12
  78. data/spec/higher_level_api/integration/exchange_unbind_spec.rb +5 -5
  79. data/spec/higher_level_api/integration/exclusive_queue_spec.rb +5 -5
  80. data/spec/higher_level_api/integration/heartbeat_spec.rb +26 -8
  81. data/spec/higher_level_api/integration/message_properties_access_spec.rb +49 -49
  82. data/spec/higher_level_api/integration/predeclared_exchanges_spec.rb +2 -2
  83. data/spec/higher_level_api/integration/publisher_confirms_spec.rb +156 -42
  84. data/spec/higher_level_api/integration/publishing_edge_cases_spec.rb +19 -19
  85. data/spec/higher_level_api/integration/queue_bind_spec.rb +23 -23
  86. data/spec/higher_level_api/integration/queue_declare_spec.rb +129 -34
  87. data/spec/higher_level_api/integration/queue_delete_spec.rb +2 -2
  88. data/spec/higher_level_api/integration/queue_purge_spec.rb +5 -5
  89. data/spec/higher_level_api/integration/queue_unbind_spec.rb +6 -6
  90. data/spec/higher_level_api/integration/read_only_consumer_spec.rb +9 -9
  91. data/spec/higher_level_api/integration/sender_selected_distribution_spec.rb +10 -10
  92. data/spec/higher_level_api/integration/tls_connection_spec.rb +224 -89
  93. data/spec/higher_level_api/integration/toxiproxy_spec.rb +76 -0
  94. data/spec/higher_level_api/integration/tx_commit_spec.rb +1 -1
  95. data/spec/higher_level_api/integration/tx_rollback_spec.rb +1 -1
  96. data/spec/higher_level_api/integration/with_channel_spec.rb +2 -2
  97. data/spec/issues/issue100_spec.rb +11 -11
  98. data/spec/issues/issue141_spec.rb +13 -14
  99. data/spec/issues/issue202_spec.rb +1 -1
  100. data/spec/issues/issue224_spec.rb +40 -0
  101. data/spec/issues/issue465_spec.rb +32 -0
  102. data/spec/issues/issue549_spec.rb +30 -0
  103. data/spec/issues/issue78_spec.rb +21 -24
  104. data/spec/issues/issue83_spec.rb +5 -6
  105. data/spec/issues/issue97_spec.rb +44 -45
  106. data/spec/lower_level_api/integration/basic_cancel_spec.rb +15 -16
  107. data/spec/lower_level_api/integration/basic_consume_spec.rb +20 -21
  108. data/spec/spec_helper.rb +8 -26
  109. data/spec/stress/channel_close_stress_spec.rb +64 -0
  110. data/spec/stress/channel_open_stress_spec.rb +15 -9
  111. data/spec/stress/channel_open_stress_with_single_threaded_connection_spec.rb +7 -7
  112. data/spec/stress/concurrent_consumers_stress_spec.rb +18 -16
  113. data/spec/stress/concurrent_publishers_stress_spec.rb +16 -19
  114. data/spec/stress/connection_open_close_spec.rb +9 -9
  115. data/spec/stress/merry_go_round_spec.rb +105 -0
  116. data/spec/tls/client_key.pem +49 -25
  117. data/spec/tls/generate-server-cert.sh +8 -0
  118. data/spec/tls/server-openssl.cnf +10 -0
  119. data/spec/tls/server.csr +16 -0
  120. data/spec/tls/server_key.pem +49 -25
  121. data/spec/toxiproxy_helper.rb +28 -0
  122. data/spec/unit/bunny_spec.rb +5 -5
  123. data/spec/unit/concurrent/atomic_fixnum_spec.rb +6 -6
  124. data/spec/unit/concurrent/condition_spec.rb +8 -8
  125. data/spec/unit/concurrent/linked_continuation_queue_spec.rb +2 -2
  126. data/spec/unit/concurrent/synchronized_sorted_set_spec.rb +16 -16
  127. data/spec/unit/exchange_recovery_spec.rb +39 -0
  128. data/spec/unit/version_delivery_tag_spec.rb +3 -3
  129. metadata +65 -47
  130. data/.ruby-version +0 -1
  131. data/lib/bunny/compatibility.rb +0 -24
  132. data/lib/bunny/system_timer.rb +0 -20
  133. data/spec/compatibility/queue_declare_spec.rb +0 -44
  134. data/spec/compatibility/queue_declare_with_default_channel_spec.rb +0 -33
  135. data/spec/higher_level_api/integration/basic_recover_spec.rb +0 -18
  136. data/spec/higher_level_api/integration/confirm_select_spec.rb +0 -19
  137. data/spec/higher_level_api/integration/consistent_hash_exchange_spec.rb +0 -50
  138. data/spec/higher_level_api/integration/merry_go_round_spec.rb +0 -85
  139. data/spec/stress/long_running_consumer_spec.rb +0 -83
  140. data/spec/tls/cacert.pem +0 -18
  141. data/spec/tls/client_cert.pem +0 -18
  142. data/spec/tls/server_cert.pem +0 -18
  143. data/spec/unit/system_timer_spec.rb +0 -10
@@ -1,18 +1,24 @@
1
1
  require "spec_helper"
2
2
 
3
3
  describe "Rapidly opening and closing lots of channels" do
4
- connection = Bunny.new(:automatic_recovery => false).tap do |c|
5
- c.start
4
+ before :all do
5
+ @connection = Bunny.new(automatic_recovery: false).tap do |c|
6
+ c.start
7
+ end
8
+ end
9
+
10
+ after :all do
11
+ @connection.close
6
12
  end
7
13
 
8
14
  context "in a single-threaded scenario" do
9
15
  let(:n) { 500 }
10
16
 
11
17
  it "works correctly" do
12
- xs = Array.new(n) { connection.create_channel }
18
+ xs = Array.new(n) { @connection.create_channel }
13
19
  puts "Opened #{n} channels"
14
20
 
15
- xs.size.should == n
21
+ expect(xs.size).to eq n
16
22
  xs.each do |ch|
17
23
  ch.close
18
24
  end
@@ -35,12 +41,12 @@ describe "Rapidly opening and closing lots of channels" do
35
41
 
36
42
  n.times do
37
43
  t = Thread.new do
38
- ch1 = connection.create_channel
39
- q = ch1.queue("", :exclusive => true)
44
+ ch1 = @connection.create_channel
45
+ q = ch1.queue("", exclusive: true)
40
46
  q.delete
41
47
  ch1.close
42
48
 
43
- ch2 = connection.create_channel
49
+ ch2 = @connection.create_channel
44
50
  ch2.close
45
51
  end
46
52
  t.abort_on_exception = true
@@ -62,8 +68,8 @@ describe "Rapidly opening and closing lots of channels" do
62
68
  n.times do
63
69
  t = Thread.new do
64
70
  3.times do
65
- ch = connection.create_channel
66
- x = ch.topic('bunny.stress.topics.t2', :durable => false)
71
+ ch = @connection.create_channel
72
+ x = ch.topic('bunny.stress.topics.t2', durable: false)
67
73
  ch.close
68
74
  end
69
75
  end
@@ -2,23 +2,23 @@ require "spec_helper"
2
2
 
3
3
  unless ENV["CI"]
4
4
  describe "Rapidly opening and closing lots of channels on a non-threaded connection" do
5
- let(:connection) do
6
- c = Bunny.new(:user => "bunny_gem", :password => "bunny_password", :vhost => "bunny_testbed", :automatic_recovery => false, :threaded => false)
7
- c.start
8
- c
5
+ before :all do
6
+ @connection = Bunny.new(username: "bunny_gem", password: "bunny_password", vhost: "bunny_testbed",
7
+ automatic_recovery: false, threaded: false)
8
+ @connection.start
9
9
  end
10
10
 
11
11
  after :all do
12
- connection.close
12
+ @connection.close
13
13
  end
14
14
 
15
15
  context "in a single-threaded scenario" do
16
16
  let(:n) { 500 }
17
17
 
18
18
  it "works correctly" do
19
- xs = Array.new(n) { connection.create_channel }
19
+ xs = Array.new(n) { @connection.create_channel }
20
20
 
21
- xs.size.should == n
21
+ expect(xs.size).to eq n
22
22
  xs.each do |ch|
23
23
  ch.close
24
24
  end
@@ -3,15 +3,14 @@ require "spec_helper"
3
3
 
4
4
  unless ENV["CI"]
5
5
  describe "Concurrent consumers sharing a connection" do
6
- let(:connection) do
7
- c = Bunny.new(:user => "bunny_gem", :password => "bunny_password", :vhost => "bunny_testbed",
8
- :automatic_recovery => false, :continuation_timeout => 6000)
9
- c.start
10
- c
6
+ before :all do
7
+ @connection = Bunny.new(username: "bunny_gem", password: "bunny_password", vhost: "bunny_testbed",
8
+ automatic_recovery: false, continuation_timeout: 45000)
9
+ @connection.start
11
10
  end
12
11
 
13
12
  after :all do
14
- connection.close
13
+ @connection.close
15
14
  end
16
15
 
17
16
  def any_not_drained?(qs)
@@ -21,17 +20,18 @@ unless ENV["CI"]
21
20
  context "when publishing thousands of messages over 128K in size" do
22
21
  let(:colors) { ["red", "blue", "white"] }
23
22
 
24
- let(:n) { 32 }
25
- let(:m) { 1000 }
23
+ let(:n) { 16 }
24
+ let(:m) { 5000 }
26
25
 
27
26
  it "successfully drain all queues" do
28
- ch = connection.create_channel
27
+ ch0 = @connection.create_channel
28
+ ch0.confirm_select
29
29
  body = "абвг"
30
- x = ch.topic("bunny.stress.concurrent.consumers.topic", :durable => true)
30
+ x = ch0.topic("bunny.stress.concurrent.consumers.topic", durable: true)
31
31
 
32
32
  chs = {}
33
33
  n.times do |i|
34
- chs[i] = connection.create_channel
34
+ chs[i] = @connection.create_channel
35
35
  end
36
36
  qs = []
37
37
 
@@ -39,8 +39,8 @@ unless ENV["CI"]
39
39
  t = Thread.new do
40
40
  cht = chs[i]
41
41
 
42
- q = cht.queue("", :exclusive => true)
43
- q.bind(x.name, :routing_key => colors.sample).subscribe do |delivery_info, meta, payload|
42
+ q = cht.queue("", exclusive: true)
43
+ q.bind(x.name, routing_key: colors.sample).subscribe do |delivery_info, meta, payload|
44
44
  # no-op
45
45
  end
46
46
  qs << q
@@ -52,17 +52,19 @@ unless ENV["CI"]
52
52
 
53
53
  5.times do |i|
54
54
  m.times do
55
- x.publish(body, :routing_key => colors.sample)
55
+ x.publish(body, routing_key: colors.sample)
56
56
  end
57
57
  puts "Published #{(i + 1) * m} messages..."
58
+ ch0.wait_for_confirms
58
59
  end
59
60
 
60
61
  while any_not_drained?(qs)
61
62
  sleep 1.0
62
63
  end
63
- puts "Drained all the queues..."
64
+ puts "Drained all queues, winding down..."
64
65
 
65
- ch.close
66
+ ch0.close
67
+ chs.each { |_, ch| ch.close }
66
68
  end
67
69
  end
68
70
  end
@@ -3,31 +3,27 @@ require "spec_helper"
3
3
 
4
4
  unless ENV["CI"]
5
5
  describe "Concurrent publishers sharing a connection" do
6
- let(:connection) do
7
- c = Bunny.new(:user => "bunny_gem", :password => "bunny_password", :vhost => "bunny_testbed", :automatically_recover => false, :continuation_timeout => 20.0)
8
- c.start
9
- c
6
+ before :all do
7
+ @connection = Bunny.new(username: "bunny_gem", password: "bunny_password",
8
+ vhost: "bunny_testbed", automatically_recover: false)
9
+ @connection.start
10
10
  end
11
11
 
12
12
  after :all do
13
- connection.close
13
+ @connection.close
14
14
  end
15
15
 
16
16
  let(:concurrency) { 24 }
17
- let(:rate) { 5_000 }
17
+ let(:messages) { 5_000 }
18
18
 
19
19
  it "successfully finish publishing" do
20
- ch = connection.create_channel
21
-
22
- q = ch.queue("", :exclusive => true)
23
20
  body = "сообщение"
24
21
 
25
- # let the queue name be sent back by RabbitMQ
26
- sleep 0.25
27
-
28
22
  chs = {}
29
23
  concurrency.times do |i|
30
- chs[i] = connection.create_channel
24
+ ch = @connection.create_channel
25
+ ch.confirm_select
26
+ chs[i] = ch
31
27
  end
32
28
 
33
29
  ts = []
@@ -35,14 +31,13 @@ unless ENV["CI"]
35
31
  concurrency.times do |i|
36
32
  t = Thread.new do
37
33
  cht = chs[i]
38
- x = ch.default_exchange
34
+ x = cht.default_exchange
39
35
 
40
- 5.times do |i|
41
- rate.times do
42
- x.publish(body, :routing_key => q.name)
43
- end
44
- puts "Published #{(i + 1) * rate} messages..."
36
+ messages.times do
37
+ x.publish(body)
45
38
  end
39
+ puts "Published #{messages} messages..."
40
+ cht.wait_for_confirms
46
41
  end
47
42
  t.abort_on_exception = true
48
43
 
@@ -52,6 +47,8 @@ unless ENV["CI"]
52
47
  ts.each do |t|
53
48
  t.join
54
49
  end
50
+
51
+ chs.each { |_, ch| ch.close }
55
52
  end
56
53
  end
57
54
  end
@@ -13,38 +13,38 @@ unless defined?(JRUBY_VERSION) && !ENV["FORCE_JRUBY_RUN"]
13
13
 
14
14
  n.times do |i|
15
15
  it "can be closed (automatic recovery disabled, take #{i})" do
16
- c = Bunny.new(:automatically_recover => false)
16
+ c = Bunny.new(automatically_recover: false)
17
17
  c.start
18
18
  ch = c.create_channel
19
19
 
20
- c.should be_connected
20
+ expect(c).to be_connected
21
21
  c.stop
22
- c.should be_closed
22
+ expect(c).to be_closed
23
23
  end
24
24
  end
25
25
 
26
26
  n.times do |i|
27
27
  it "can be closed (automatic recovery enabled, take #{i})" do
28
- c = Bunny.new(:automatically_recover => true)
28
+ c = Bunny.new(automatically_recover: true)
29
29
  c.start
30
30
  ch = c.create_channel
31
31
 
32
- c.should be_connected
32
+ expect(c).to be_connected
33
33
  c.stop
34
- c.should be_closed
34
+ expect(c).to be_closed
35
35
  end
36
36
  end
37
37
 
38
38
  context "in the single threaded mode" do
39
39
  n.times do |i|
40
40
  it "can be closed (single threaded mode, take #{i})" do
41
- c = Bunny.new(:automatically_recover => false, :threaded => false)
41
+ c = Bunny.new(automatically_recover: false, threaded: false)
42
42
  c.start
43
43
  ch = c.create_channel
44
44
 
45
- c.should be_connected
45
+ expect(c).to be_connected
46
46
  c.stop
47
- c.should be_closed
47
+ expect(c).to be_closed
48
48
  end
49
49
  end
50
50
  end
@@ -0,0 +1,105 @@
1
+ require "spec_helper"
2
+
3
+ describe "A batch of messages proxied by multiple intermediate consumers" do
4
+ let(:c1) do
5
+ c = Bunny.new(username: "bunny_gem",
6
+ password: "bunny_password",
7
+ vhost: "bunny_testbed",
8
+ heartbeat_timeout: 6)
9
+ c.start
10
+ c
11
+ end
12
+
13
+ let(:c2) do
14
+ c = Bunny.new(username: "bunny_gem",
15
+ password: "bunny_password",
16
+ vhost: "bunny_testbed",
17
+ heartbeat_timeout: 6)
18
+ c.start
19
+ c
20
+ end
21
+
22
+ let(:c3) do
23
+ c = Bunny.new(username: "bunny_gem",
24
+ password: "bunny_password",
25
+ vhost: "bunny_testbed",
26
+ heartbeat_timeout: 6)
27
+ c.start
28
+ c
29
+ end
30
+
31
+ let(:c4) do
32
+ c = Bunny.new(username: "bunny_gem",
33
+ password: "bunny_password",
34
+ vhost: "bunny_testbed",
35
+ heartbeat_timeout: 6)
36
+ c.start
37
+ c
38
+ end
39
+
40
+ let(:c5) do
41
+ c = Bunny.new(username: "bunny_gem",
42
+ password: "bunny_password",
43
+ vhost: "bunny_testbed",
44
+ heartbeat_timeout: 6)
45
+ c.start
46
+ c
47
+ end
48
+
49
+ after :each do
50
+ [c1, c2, c3, c4, c5].each do |c|
51
+ c.close if c.open?
52
+ end
53
+ end
54
+
55
+ [1000, 5_000, 10_000, 20_000, 30_000, 50_000].each do |n|
56
+ # message flow is as follows:
57
+ #
58
+ # x => q4 => q3 => q2 => q1 => xs (results)
59
+ it "successfully reaches its final destination (batch size: #{n})" do
60
+ xs = []
61
+
62
+ ch1 = c1.create_channel
63
+ q1 = ch1.queue("", exclusive: true)
64
+ q1.subscribe(manual_ack: true) do |delivery_info, _, payload|
65
+ xs << payload
66
+ ch1.ack(delivery_info.delivery_tag)
67
+ end
68
+
69
+ ch2 = c2.create_channel
70
+ q2 = ch2.queue("", exclusive: true)
71
+ q2.subscribe do |_, _, payload|
72
+ q1.publish(payload)
73
+ end
74
+
75
+ ch3 = c3.create_channel(nil, 2)
76
+ q3 = ch3.queue("", exclusive: true)
77
+ q3.subscribe(manual_ack: true) do |delivery_info, _, payload|
78
+ q2.publish(payload)
79
+ ch3.ack(delivery_info.delivery_tag)
80
+ end
81
+
82
+ ch4 = c4.create_channel(nil, 4)
83
+ q4 = ch4.queue("", exclusive: true)
84
+ q4.subscribe do |_, _, payload|
85
+ q3.publish(payload)
86
+ end
87
+
88
+ ch5 = c5.create_channel(nil, 8)
89
+ x = ch5.default_exchange
90
+
91
+ n.times do |i|
92
+ x.publish("msg #{i}", routing_key: q4.name)
93
+ end
94
+
95
+ Bunny::TestKit.poll_until(90) do
96
+ xs.size >= n
97
+ end
98
+
99
+ expect(xs.size).to eq n
100
+ expect(xs.last).to eq "msg #{n - 1}"
101
+
102
+ [q1, q2, q3, q4].each { |q| q.delete }
103
+ end
104
+ end
105
+ end
@@ -1,27 +1,51 @@
1
1
  -----BEGIN RSA PRIVATE KEY-----
2
- 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
- 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
- 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
- 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
- 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
- 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
- siGEn71LTU979DxCTzvzILpSjRGU6ih6LQuM758ejXBwAZzLtjSgonJ7CoAAz+ou
9
- EwfSYRquxzTbUpfKogWlE8qJouV1BzYxbCIt5DZF+OqnzMnuMpPfwrStVbXZ5Z4p
10
- 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
- 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
- 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
- erwQs2ECgYEA/nTWap6M7InOeAkosEEeLcu0idnjxlT/OToRtfdNkKatvqAFpSDd
14
- 2IBzr3kH+qGToeF8B7uJBaWO69m28+yEngWNW1u0KICUTTzlKZqSqNy1nxWnCWVk
15
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
27
51
  -----END RSA PRIVATE KEY-----