kcl-rb 1.0.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 (49) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/main.yml +58 -0
  3. data/.gitignore +11 -0
  4. data/.rubocop.yml +93 -0
  5. data/.ruby-version +1 -0
  6. data/Gemfile +4 -0
  7. data/Gemfile.lock +90 -0
  8. data/LICENSE.txt +21 -0
  9. data/README.md +130 -0
  10. data/Rakefile +2 -0
  11. data/aws/config +3 -0
  12. data/aws/credentials +3 -0
  13. data/bin/console +14 -0
  14. data/bin/setup +8 -0
  15. data/demo/Gemfile +5 -0
  16. data/demo/Gemfile.lock +60 -0
  17. data/demo/README.md +38 -0
  18. data/demo/Rakefile +31 -0
  19. data/demo/aws/config +3 -0
  20. data/demo/aws/credentials +3 -0
  21. data/demo/docker-compose.yml +23 -0
  22. data/demo/lib/kcl_demo.rb +49 -0
  23. data/demo/lib/kcl_demo/demo_record_processor.rb +43 -0
  24. data/demo/lib/kcl_demo/demo_record_processor_factory.rb +7 -0
  25. data/demo/terraform/main.tf +35 -0
  26. data/docker-compose.yml +22 -0
  27. data/kcl-rb.gemspec +36 -0
  28. data/lib/kcl.rb +32 -0
  29. data/lib/kcl/checkpointer.rb +179 -0
  30. data/lib/kcl/checkpoints/sentinel.rb +17 -0
  31. data/lib/kcl/config.rb +35 -0
  32. data/lib/kcl/errors.rb +6 -0
  33. data/lib/kcl/logger.rb +3 -0
  34. data/lib/kcl/proxies/dynamo_db_proxy.rb +132 -0
  35. data/lib/kcl/proxies/kinesis_proxy.rb +56 -0
  36. data/lib/kcl/record_processor.rb +13 -0
  37. data/lib/kcl/record_processor_factory.rb +5 -0
  38. data/lib/kcl/types/extended_sequence_number.rb +89 -0
  39. data/lib/kcl/types/initialization_input.rb +13 -0
  40. data/lib/kcl/types/records_input.rb +15 -0
  41. data/lib/kcl/types/shutdown_input.rb +13 -0
  42. data/lib/kcl/version.rb +3 -0
  43. data/lib/kcl/worker.rb +159 -0
  44. data/lib/kcl/workers/consumer.rb +80 -0
  45. data/lib/kcl/workers/record_checkpointer.rb +14 -0
  46. data/lib/kcl/workers/shard_info.rb +47 -0
  47. data/lib/kcl/workers/shutdown_reason.rb +6 -0
  48. data/terraform/main.tf +35 -0
  49. metadata +191 -0
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'kcl-rb', path: '../'
4
+ gem 'pry'
5
+ gem 'rake', '~> 12.0'
@@ -0,0 +1,60 @@
1
+ PATH
2
+ remote: ..
3
+ specs:
4
+ kcl-rb (1.0.0)
5
+ activesupport (>= 5.0)
6
+ aws-sdk-dynamodb (~> 1)
7
+ aws-sdk-kinesis (~> 1)
8
+ eventmachine (~> 1.2.7)
9
+
10
+ GEM
11
+ remote: https://rubygems.org/
12
+ specs:
13
+ activesupport (6.0.3.1)
14
+ concurrent-ruby (~> 1.0, >= 1.0.2)
15
+ i18n (>= 0.7, < 2)
16
+ minitest (~> 5.1)
17
+ tzinfo (~> 1.1)
18
+ zeitwerk (~> 2.2, >= 2.2.2)
19
+ aws-eventstream (1.1.0)
20
+ aws-partitions (1.326.0)
21
+ aws-sdk-core (3.98.0)
22
+ aws-eventstream (~> 1, >= 1.0.2)
23
+ aws-partitions (~> 1, >= 1.239.0)
24
+ aws-sigv4 (~> 1.1)
25
+ jmespath (~> 1.0)
26
+ aws-sdk-dynamodb (1.48.0)
27
+ aws-sdk-core (~> 3, >= 3.71.0)
28
+ aws-sigv4 (~> 1.1)
29
+ aws-sdk-kinesis (1.23.0)
30
+ aws-sdk-core (~> 3, >= 3.71.0)
31
+ aws-sigv4 (~> 1.1)
32
+ aws-sigv4 (1.1.4)
33
+ aws-eventstream (~> 1.0, >= 1.0.2)
34
+ coderay (1.1.3)
35
+ concurrent-ruby (1.1.6)
36
+ eventmachine (1.2.7)
37
+ i18n (1.8.3)
38
+ concurrent-ruby (~> 1.0)
39
+ jmespath (1.4.0)
40
+ method_source (1.0.0)
41
+ minitest (5.14.1)
42
+ pry (0.13.1)
43
+ coderay (~> 1.1)
44
+ method_source (~> 1.0)
45
+ rake (12.3.3)
46
+ thread_safe (0.3.6)
47
+ tzinfo (1.2.7)
48
+ thread_safe (~> 0.1)
49
+ zeitwerk (2.3.0)
50
+
51
+ PLATFORMS
52
+ ruby
53
+
54
+ DEPENDENCIES
55
+ kcl-rb!
56
+ pry
57
+ rake (~> 12.0)
58
+
59
+ BUNDLED WITH
60
+ 2.1.4
@@ -0,0 +1,38 @@
1
+ # kcl-rb Demo App
2
+
3
+ ## Build and Run
4
+
5
+ Run localstack container (mock for Kinesis and DynamoDB).
6
+
7
+ ```
8
+ $ docker-compose up
9
+ ```
10
+
11
+ Create resources on localstack using Terraform
12
+
13
+ ```
14
+ $ cd terraform
15
+ $ terraform init
16
+ $ terraform plan
17
+ $ terraform apply
18
+ ```
19
+
20
+ Build dependencies
21
+
22
+ ```
23
+ $ bundle install --path vendor/bundle
24
+ ```
25
+
26
+ Run Demo KCL application
27
+
28
+ ```
29
+ $ bundle exec rake run
30
+ ```
31
+
32
+ Put records to Kinesis stream
33
+
34
+ ```
35
+ $ RECORD_COUNT=10 bundle exec rake seed
36
+ ```
37
+
38
+ You can see in console that the input data is distributed and processed by each consumer.
@@ -0,0 +1,31 @@
1
+ require 'bundler/setup'
2
+ require 'pry'
3
+
4
+ require 'kcl'
5
+ require_relative './lib/kcl_demo'
6
+
7
+ task :default => :run
8
+ task :run do
9
+ KclDemo::App.initialize
10
+ KclDemo::App.run
11
+ end
12
+
13
+ task :seed do
14
+ KclDemo::App.initialize
15
+ record_count = Integer(ENV['RECORD_COUNT'] ||0)
16
+ if record_count.zero?
17
+ puts 'Set over 1 for RECORD_COUNT'
18
+ return
19
+ end
20
+ KclDemo::App.seed(record_count)
21
+ end
22
+
23
+ task :debug do
24
+ KclDemo::App.initialize
25
+
26
+ kinesis = Kcl::Proxies::KinesisProxy.new(KclDemo::App.config)
27
+ dynamodb = Kcl::Proxies::DynamoDbProxy.new(KclDemo::App.config)
28
+ # rubocop:disable Lint/Debugger
29
+ binding.pry
30
+ # rubocop:enable Lint/Debugger
31
+ end
@@ -0,0 +1,3 @@
1
+ [default]
2
+ region = ap-northeast-1
3
+ output = json
@@ -0,0 +1,3 @@
1
+ [default]
2
+ aws_access_key_id = dummy
3
+ aws_secret_access_key = dummy
@@ -0,0 +1,23 @@
1
+ version: '3'
2
+
3
+ volumes:
4
+ localstack-data:
5
+ driver: local
6
+
7
+ services:
8
+ localstack:
9
+ image: localstack/localstack:0.11.0
10
+ container_name: localstack-for-kcl-demo
11
+ ports:
12
+ - "8080:8080"
13
+ - "4566:4566"
14
+ environment:
15
+ - DATA_DIR=/tmp/localstack/data
16
+ - DEBUG=${LOCALSTACK_DEBUG:-true}
17
+ - DEFAULT_REGION=ap-northeast-1
18
+ - SERVICES=dynamodb,kinesis
19
+ - USE_SSL=true
20
+ volumes:
21
+ - "${PWD}/aws:/root/.aws"
22
+ - "/var/run/docker.sock:/var/run/docker.sock"
23
+ - "localstack-data:/tmp/localstack"
@@ -0,0 +1,49 @@
1
+ require 'json'
2
+ require 'securerandom'
3
+
4
+ require_relative './kcl_demo/demo_record_processor'
5
+ require_relative './kcl_demo/demo_record_processor_factory'
6
+
7
+ module KclDemo
8
+ class App
9
+ def self.initialize
10
+ Kcl.configure do |config|
11
+ config.aws_region = 'ap-northeast-1'
12
+ config.aws_access_key_id = 'dummy'
13
+ config.aws_secret_access_key = 'dummy'
14
+ config.dynamodb_endpoint = 'https://localhost:4566'
15
+ config.dynamodb_table_name = 'kcl-rb-demo'
16
+ config.kinesis_endpoint = 'https://localhost:4566'
17
+ config.kinesis_stream_name = 'kcl-rb-demo'
18
+ config.use_ssl = false
19
+ end
20
+ end
21
+
22
+ def self.config
23
+ Kcl.config
24
+ end
25
+
26
+ def self.run
27
+ factory = KclDemo::DemoRecordProcessorFactory.new
28
+ Kcl::Worker.run('kcl-demo', factory)
29
+ end
30
+
31
+ def self.seed(record_count = 1000)
32
+ proxy = Kcl::Proxies::KinesisProxy.new(config)
33
+
34
+ # puts records
35
+ record_count.times do |i|
36
+ str = SecureRandom.alphanumeric
37
+ hash = JSON.generate({ id: i, name: str })
38
+ resp = proxy.put_record(
39
+ {
40
+ stream_name: config.kinesis_stream_name,
41
+ data: Base64.strict_encode64(hash),
42
+ partition_key: str
43
+ }
44
+ )
45
+ puts resp
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,43 @@
1
+ require 'pry'
2
+
3
+ module KclDemo
4
+ class DemoRecordProcessor < Kcl::RecordProcessor
5
+ # @implement
6
+ def after_initialize(initialization_input)
7
+ Kcl.logger.info("Initialization at #{initialization_input}")
8
+ end
9
+
10
+ # @implement
11
+ def process_records(records_input)
12
+ Kcl.logger.info('Processing records...')
13
+
14
+ # レコードのリストを取得
15
+ return if records_input.records.empty?
16
+
17
+ # rubocop:disable Lint/Debugger
18
+ binding.pry if ENV['DEBUG'] == '1'
19
+ # rubocop:enable Lint/Debugger
20
+
21
+ records_input.records.each do |record|
22
+ Kcl.logger.info("Record = #{record}")
23
+ end
24
+
25
+ # チェックポイントを記録
26
+ last_sequence_number = records_input.records[-1].sequence_number
27
+ Kcl.logger.info(
28
+ "Checkpoint progress at: #{last_sequence_number}" \
29
+ ", MillisBehindLatest = #{records_input.millis_behind_latest}"
30
+ )
31
+ records_input.record_checkpointer.update_checkpoint(last_sequence_number)
32
+ end
33
+
34
+ # @implement
35
+ def shutdown(shutdown_input)
36
+ Kcl.logger.info("Shutdown reason: #{shutdown_input.shutdown_reason}")
37
+
38
+ if shutdown_input.shutdown_reason == Kcl::Workers::ShutdownReason::TERMINATE
39
+ shutdown_input.record_checkpointer.update_checkpoint(nil)
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,7 @@
1
+ module KclDemo
2
+ class DemoRecordProcessorFactory < Kcl::RecordProcessorFactory
3
+ def create_processor
4
+ KclDemo::DemoRecordProcessor.new
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,35 @@
1
+ #-------------------------------------------------------------------------------
2
+ # 開発環境 (LocalStack)
3
+ #-------------------------------------------------------------------------------
4
+
5
+ provider "aws" {
6
+ version = "~> 2.60"
7
+ access_key = "dummy"
8
+ secret_key = "dummy"
9
+ region = "ap-northeast-1"
10
+ insecure = true
11
+ skip_credentials_validation = true
12
+ skip_metadata_api_check = true
13
+ skip_requesting_account_id = true
14
+
15
+ endpoints {
16
+ dynamodb = "https://localhost:4566"
17
+ kinesis = "https://localhost:4566"
18
+ }
19
+ }
20
+
21
+
22
+ #-------------------------------------------------------------------------------
23
+ # Kinesis stream
24
+ #-------------------------------------------------------------------------------
25
+
26
+ resource "aws_kinesis_stream" "kcl-rb-demo_stream" {
27
+ name = "kcl-rb-demo"
28
+ shard_count = 5
29
+ retention_period = 24
30
+
31
+ tags = {
32
+ Environment = "test"
33
+ }
34
+ }
35
+
@@ -0,0 +1,22 @@
1
+ version: '3'
2
+
3
+ volumes:
4
+ localstack-data:
5
+ driver: local
6
+
7
+ services:
8
+ localstack:
9
+ image: localstack/localstack:0.11.0
10
+ container_name: localstack-for-kcl
11
+ ports:
12
+ - "8080:8080"
13
+ - "4566:4566"
14
+ environment:
15
+ - DATA_DIR=/tmp/localstack/data
16
+ - DEBUG=${LOCALSTACK_DEBUG:-true}
17
+ - DEFAULT_REGION=ap-northeast-1
18
+ - SERVICES=dynamodb,kinesis
19
+ - USE_SSL=true
20
+ volumes:
21
+ - "${PWD}/aws:/root/.aws"
22
+ - "localstack-data:/tmp/localstack"
@@ -0,0 +1,36 @@
1
+ require_relative 'lib/kcl/version'
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = 'kcl-rb'
5
+ spec.version = Kcl::VERSION
6
+ spec.authors = ['yo_waka']
7
+ spec.email = ['y.wakahara@gmail.com']
8
+
9
+ spec.summary = 'Amazon.Kinesis Client Library for Ruby.'
10
+ spec.description = 'A pure ruby interface for Amazon Kinesis Client.'
11
+ spec.homepage = 'https://github.com/waka/kcl-rb'
12
+ spec.license = 'MIT'
13
+ spec.required_ruby_version = Gem::Requirement.new('>= 2.3.0')
14
+
15
+ spec.metadata['homepage_uri'] = spec.homepage
16
+ spec.metadata['source_code_uri'] = 'https://github.com/waka/kcl-rb'
17
+ spec.metadata['changelog_uri'] = 'https://github.com/waka/kcl-rb/CHANGELOG'
18
+
19
+ # Specify which files should be added to the gem when it is released.
20
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
21
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
22
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
23
+ end
24
+ spec.bindir = 'exe'
25
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
26
+ spec.require_paths = ['lib']
27
+
28
+ spec.add_dependency 'activesupport', '>= 5.0'
29
+ spec.add_dependency 'aws-sdk-dynamodb', '~> 1'
30
+ spec.add_dependency 'aws-sdk-kinesis', '~> 1'
31
+ spec.add_dependency 'eventmachine', '~> 1.2.7'
32
+
33
+ spec.add_development_dependency 'rake', '~> 12.0'
34
+ spec.add_development_dependency 'rspec', '~> 3.0'
35
+ spec.add_development_dependency 'rubocop', '~> 0.86.0'
36
+ end
@@ -0,0 +1,32 @@
1
+ require 'kcl/checkpointer'
2
+ require 'kcl/checkpoints/sentinel'
3
+ require 'kcl/config'
4
+ require 'kcl/errors'
5
+ require 'kcl/logger'
6
+ require 'kcl/proxies/dynamo_db_proxy'
7
+ require 'kcl/proxies/kinesis_proxy'
8
+ require 'kcl/record_processor'
9
+ require 'kcl/record_processor_factory'
10
+ require 'kcl/types/extended_sequence_number'
11
+ require 'kcl/types/initialization_input'
12
+ require 'kcl/types/records_input'
13
+ require 'kcl/types/shutdown_input'
14
+ require 'kcl/worker'
15
+ require 'kcl/workers/consumer'
16
+ require 'kcl/workers/record_checkpointer'
17
+ require 'kcl/workers/shard_info'
18
+ require 'kcl/workers/shutdown_reason'
19
+
20
+ module Kcl
21
+ def self.configure
22
+ yield config
23
+ end
24
+
25
+ def self.config
26
+ @_config ||= Kcl::Config.new
27
+ end
28
+
29
+ def self.logger
30
+ @_logger ||= (config.logger || Kcl::Logger.new($stdout))
31
+ end
32
+ end
@@ -0,0 +1,179 @@
1
+ require 'time'
2
+
3
+ class Kcl::Checkpointer
4
+ DYNAMO_DB_LEASE_PRIMARY_KEY = 'shard_id'.freeze
5
+ DYNAMO_DB_LEASE_OWNER_KEY = 'assigned_to'.freeze
6
+ DYNAMO_DB_LEASE_TIMEOUT_KEY = 'lease_timeout'.freeze
7
+ DYNAMO_DB_CHECKPOINT_SEQUENCE_NUMBER_KEY = 'checkpoint'.freeze
8
+ DYNAMO_DB_PARENT_SHARD_KEY = 'parent_shard_id'.freeze
9
+
10
+ attr_reader :dynamodb
11
+
12
+ # @param [Kcl::Config] config
13
+ def initialize(config)
14
+ @dynamodb = Kcl::Proxies::DynamoDbProxy.new(config)
15
+ @table_name = config.dynamodb_table_name
16
+
17
+ return if @dynamodb.exists?(@table_name)
18
+ @dynamodb.create_table(
19
+ @table_name,
20
+ [{
21
+ attribute_name: DYNAMO_DB_LEASE_PRIMARY_KEY,
22
+ attribute_type: 'S'
23
+ }],
24
+ [{
25
+ attribute_name: DYNAMO_DB_LEASE_PRIMARY_KEY,
26
+ key_type: 'HASH'
27
+ }],
28
+ {
29
+ read_capacity_units: config.dynamodb_read_capacity,
30
+ write_capacity_units: config.dynamodb_write_capacity
31
+ }
32
+ )
33
+ Kcl.logger.info("Created DynamoDB table: #{@table_name}")
34
+ end
35
+
36
+ # Retrieves the checkpoint for the given shard
37
+ # @params [Kcl::Workers::ShardInfo] shard
38
+ # @return [Kcl::Workers::ShardInfo]
39
+ def fetch_checkpoint(shard)
40
+ checkpoint = @dynamodb.get_item(
41
+ @table_name,
42
+ { "#{DYNAMO_DB_LEASE_PRIMARY_KEY}" => shard.shard_id }
43
+ )
44
+ return shard if checkpoint.nil?
45
+
46
+ if checkpoint[DYNAMO_DB_CHECKPOINT_SEQUENCE_NUMBER_KEY]
47
+ shard.checkpoint = checkpoint[DYNAMO_DB_CHECKPOINT_SEQUENCE_NUMBER_KEY]
48
+ end
49
+ if checkpoint[DYNAMO_DB_LEASE_OWNER_KEY]
50
+ shard.assigned_to = checkpoint[DYNAMO_DB_LEASE_OWNER_KEY]
51
+ end
52
+ Kcl.logger.info("Retrieves checkpoint of shard at #{shard.to_h}")
53
+
54
+ shard
55
+ end
56
+
57
+ # Write the checkpoint for the given shard
58
+ # @params [Kcl::Workers::ShardInfo] shard
59
+ # @return [Kcl::Workers::ShardInfo]
60
+ def update_checkpoint(shard)
61
+ item = {
62
+ "#{DYNAMO_DB_LEASE_PRIMARY_KEY}" => shard.shard_id,
63
+ "#{DYNAMO_DB_CHECKPOINT_SEQUENCE_NUMBER_KEY}" => shard.checkpoint,
64
+ "#{DYNAMO_DB_LEASE_OWNER_KEY}" => shard.assigned_to,
65
+ "#{DYNAMO_DB_LEASE_TIMEOUT_KEY}" => shard.lease_timeout.to_s
66
+ }
67
+ if shard.parent_shard_id > 0
68
+ item[DYNAMO_DB_PARENT_SHARD_KEY] = shard.parent_shard_id
69
+ end
70
+
71
+ result = @dynamodb.put_item(@table_name, item)
72
+ if result
73
+ Kcl.logger.info("Write checkpoint of shard at #{shard.to_h}")
74
+ else
75
+ Kcl.logger.info("Failed to write checkpoint for shard at #{shard.to_h}")
76
+ end
77
+
78
+ shard
79
+ end
80
+
81
+ # Attempt to gain a lock on the given shard
82
+ # @params [Kcl::Workers::ShardInfo] shard
83
+ # @params [String] next_assigned_to
84
+ # @return [Kcl::Workers::ShardInfo]
85
+ def lease(shard, next_assigned_to)
86
+ now = Time.now.utc
87
+ next_lease_timeout = now + Kcl.config.dynamodb_failover_seconds
88
+
89
+ checkpoint = @dynamodb.get_item(
90
+ @table_name,
91
+ { "#{DYNAMO_DB_LEASE_PRIMARY_KEY}" => shard.shard_id }
92
+ )
93
+ assigned_to = checkpoint && checkpoint[DYNAMO_DB_LEASE_OWNER_KEY]
94
+ lease_timeout = checkpoint && checkpoint[DYNAMO_DB_LEASE_TIMEOUT_KEY]
95
+
96
+ if assigned_to && lease_timeout
97
+ if now > Time.parse(lease_timeout) && assigned_to != next_assigned_to
98
+ raise Kcl::Errors::LeaseNotAquiredError
99
+ end
100
+ condition_expression = 'shard_id = :shard_id AND assigned_to = :assigned_to AND lease_timeout = :lease_timeout'
101
+ expression_attributes = {
102
+ ':shard_id' => shard.shard_id,
103
+ ':assigned_to' => assigned_to,
104
+ ':lease_timeout' => lease_timeout
105
+ }
106
+ Kcl.logger.info("Attempting to get a lock for shard: #{shard.to_h}")
107
+ else
108
+ condition_expression = 'attribute_not_exists(assigned_to)'
109
+ expression_attributes = nil
110
+ end
111
+
112
+ item = {
113
+ "#{DYNAMO_DB_LEASE_PRIMARY_KEY}" => shard.shard_id,
114
+ "#{DYNAMO_DB_LEASE_OWNER_KEY}" => next_assigned_to,
115
+ "#{DYNAMO_DB_LEASE_TIMEOUT_KEY}" => next_lease_timeout.to_s
116
+ }
117
+ if shard.checkpoint != ''
118
+ item[DYNAMO_DB_CHECKPOINT_SEQUENCE_NUMBER_KEY] = shard.checkpoint
119
+ end
120
+ if shard.parent_shard_id > 0
121
+ item[DYNAMO_DB_PARENT_SHARD_KEY] = shard.parent_shard_id
122
+ end
123
+
124
+ result = @dynamodb.conditional_update_item(
125
+ @table_name,
126
+ item,
127
+ condition_expression,
128
+ expression_attributes
129
+ )
130
+ if result
131
+ shard.assigned_to = next_assigned_to
132
+ shard.lease_timeout = next_lease_timeout
133
+ Kcl.logger.info("Get lease for shard at #{shard.to_h}")
134
+ else
135
+ Kcl.logger.info("Failed to get lease for shard at #{shard.to_h}")
136
+ end
137
+
138
+ shard
139
+ end
140
+
141
+ # Remove the shard entry
142
+ # @params [Kcl::Workers::ShardInfo] shard
143
+ # @return [Kcl::Workers::ShardInfo]
144
+ def remove_lease(shard)
145
+ result = @dynamodb.remove_item(
146
+ @table_name,
147
+ { "#{DYNAMO_DB_LEASE_PRIMARY_KEY}" => shard.shard_id }
148
+ )
149
+ if result
150
+ shard.assigned_to = nil
151
+ shard.checkpoint = nil
152
+ shard.lease_timeout = nil
153
+ Kcl.logger.info("Remove lease for shard at #{shard.to_h}")
154
+ else
155
+ Kcl.logger.info("Failed to remove lease for shard at #{shard.to_h}")
156
+ end
157
+
158
+ shard
159
+ end
160
+
161
+ # Remove lease owner for the shard entry
162
+ # @params [Kcl::Workers::ShardInfo] shard
163
+ # @return [Kcl::Workers::ShardInfo]
164
+ def remove_lease_owner(shard)
165
+ result = @dynamodb.update_item(
166
+ @table_name,
167
+ { "#{DYNAMO_DB_LEASE_PRIMARY_KEY}" => shard.shard_id },
168
+ "remove #{DYNAMO_DB_LEASE_OWNER_KEY}"
169
+ )
170
+ if result
171
+ shard.assigned_to = nil
172
+ Kcl.logger.info("Remove lease owner for shard at #{shard.to_h}")
173
+ else
174
+ Kcl.logger.info("Failed to remove lease owner for shard at #{shard.to_h}")
175
+ end
176
+
177
+ shard
178
+ end
179
+ end