fluent-plugin-bigquery 3.2.0 → 3.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 762f6e4f78f96c8c6912dbdd5780aa9b79902bbe7ca2df7dee60dcc0897c0e80
4
- data.tar.gz: ff7e0e61dddb066bdeced537521255743aa1b98cbc2e539a1e2076e4ef93d9ae
3
+ metadata.gz: 9b5175251ba70839fdc94328056d8737ec746a866e607ad1f485889dc2a4f3df
4
+ data.tar.gz: cbfb3fb3adfbf8958a9acd3283b350e532c9805ec712f8615537bba82734ee63
5
5
  SHA512:
6
- metadata.gz: 0e1bd8c1cfca5dd43bebb2e9b4e2b4e2630c9e6176e1a03606b3ac2c289f23e049d4b8333bc39fbbc0142cb4dc66de2437fdd1e46c2c69c283e6e8db895f7ca6
7
- data.tar.gz: 0a55797f85a64d787020c443041fb3ee2f08525238122ab1ff51f901467c2a349fa3678726e1ac09e25bcb97b141c5168f66192bcd40319355e6dd212793db94
6
+ metadata.gz: 55804c377380fa2c99e3a8e90bfe64b9ba64012df821d8b549e594e17f408f00c8ce00721261c413cbd4882c7e4b2e2be58ac2d4e3c061599ebf7716b7228d23
7
+ data.tar.gz: 20e8621b27f42115ce156ec933e361a45d3db057550d4858e0610de29ebfca5949ac1dff4d33e730a40e238531f5f92ec31d2ca23934a5be70a60a48df71b01d
data/.gitignore CHANGED
@@ -20,3 +20,5 @@ script/
20
20
  .idea/
21
21
 
22
22
  fluentd-0.12
23
+
24
+ integration/log
data/README.md CHANGED
@@ -45,7 +45,6 @@ Because embedded gem dependency sometimes restricts ruby environment.
45
45
  | private_key_path | string | yes (private_key) | no | nil | GCP Private Key file path |
46
46
  | private_key_passphrase | string | yes (private_key) | no | nil | GCP Private Key Passphrase |
47
47
  | json_key | string | yes (json_key) | no | nil | GCP JSON Key file path or JSON Key string |
48
- | location | string | no | no | nil | BigQuery Data Location. The geographic location of the job. Required except for US and EU. |
49
48
  | project | string | yes | yes | nil | |
50
49
  | dataset | string | yes | yes | nil | |
51
50
  | table | string | yes (either `tables`) | yes | nil | |
@@ -5,6 +5,7 @@ module Fluent
5
5
  RETRYABLE_ERROR_REASON = %w(backendError internalError rateLimitExceeded tableUnavailable).freeze
6
6
  RETRYABLE_INSERT_ERRORS_REASON = %w(timeout backendError internalError rateLimitExceeded).freeze
7
7
  RETRYABLE_STATUS_CODE = [500, 502, 503, 504]
8
+ REGION_NOT_WRITABLE_MESSAGE = -"is not writable in the region"
8
9
 
9
10
  class << self
10
11
  # @param e [Google::Apis::Error]
@@ -19,6 +20,10 @@ module Fluent
19
20
 
20
21
  # @param e [Google::Apis::Error]
21
22
  def retryable_error?(e)
23
+ retryable_server_error?(e) || retryable_region_not_writable?(e)
24
+ end
25
+
26
+ def retryable_server_error?(e)
22
27
  e.is_a?(Google::Apis::ServerError) && RETRYABLE_STATUS_CODE.include?(e.status_code)
23
28
  end
24
29
 
@@ -30,6 +35,10 @@ module Fluent
30
35
  RETRYABLE_INSERT_ERRORS_REASON.include?(reason)
31
36
  end
32
37
 
38
+ def retryable_region_not_writable?(e)
39
+ e.is_a?(Google::Apis::ClientError) && e.status_code == 400 && e.message.include?(REGION_NOT_WRITABLE_MESSAGE)
40
+ end
41
+
33
42
  # Guard for instantiation
34
43
  private :new
35
44
  def inherited(subclass)
@@ -1,5 +1,5 @@
1
1
  module Fluent
2
2
  module BigQueryPlugin
3
- VERSION = "3.2.0".freeze
3
+ VERSION = "3.3.1".freeze
4
4
  end
5
5
  end
@@ -101,6 +101,7 @@ module Fluent
101
101
  end
102
102
  end
103
103
  rescue Google::Apis::ServerError, Google::Apis::ClientError, Google::Apis::AuthorizationError => e
104
+ log.debug "insert error: #{e.message}", status_code: e.respond_to?(:status_code) ? e.status_code : nil, reason: e.respond_to?(:reason) ? e.reason : nil
104
105
  error_data = { project_id: project, dataset: dataset, table: table_id, code: e.status_code, message: e.message }
105
106
  wrapped = Fluent::BigQuery::Error.wrap(e)
106
107
  if wrapped.retryable?
@@ -112,7 +113,7 @@ module Fluent
112
113
  raise wrapped
113
114
  end
114
115
 
115
- JobReference = Struct.new(:chunk_id, :chunk_id_hex, :project_id, :dataset_id, :table_id, :job_id) do
116
+ JobReference = Struct.new(:chunk_id, :chunk_id_hex, :project_id, :dataset_id, :table_id, :job_id, :location) do
116
117
  def as_hash(*keys)
117
118
  if keys.empty?
118
119
  to_h
@@ -143,8 +144,8 @@ module Fluent
143
144
  configuration.merge!({job_reference: {project_id: project, job_id: job_id}}) if job_id
144
145
 
145
146
  begin
146
- # Check table existance
147
- client.get_table(project, dataset, table_id)
147
+ # Check table existance and use its location for the result when the load jobs is duplicated.
148
+ table = client.get_table(project, dataset, table_id)
148
149
  rescue Google::Apis::ServerError, Google::Apis::ClientError, Google::Apis::AuthorizationError => e
149
150
  if e.status_code == 404 && /Not Found: Table/i =~ e.message
150
151
  raise Fluent::BigQuery::UnRetryableError.new("Table is not found") unless @options[:auto_create_table]
@@ -161,12 +162,14 @@ module Fluent
161
162
  upload_source: upload_source,
162
163
  content_type: "application/octet-stream",
163
164
  )
164
- JobReference.new(chunk_id, chunk_id_hex, project, dataset, table_id, res.job_reference.job_id)
165
+ JobReference.new(chunk_id, chunk_id_hex, project, dataset, table_id, res.job_reference.job_id, res.job_reference.location)
165
166
  rescue Google::Apis::ServerError, Google::Apis::ClientError, Google::Apis::AuthorizationError => e
166
167
  log.error "job.load API", project_id: project, dataset: dataset, table: table_id, code: e.status_code, message: e.message
167
168
 
168
169
  if job_id && e.status_code == 409 && e.message =~ /Job/ # duplicate load job
169
- return JobReference.new(chunk_id, chunk_id_hex, project, dataset, table_id, job_id)
170
+ # If a load job is duplicated, the API response may not be available to create the result.
171
+ # Therefore, we need to use the location of the table instead of the job's location to determine the result.
172
+ return JobReference.new(chunk_id, chunk_id_hex, project, dataset, table_id, job_id, table.location)
170
173
  end
171
174
 
172
175
  raise Fluent::BigQuery::Error.wrap(e)
@@ -175,7 +178,7 @@ module Fluent
175
178
  def fetch_load_job(job_reference)
176
179
  project = job_reference.project_id
177
180
  job_id = job_reference.job_id
178
- location = @options[:location]
181
+ location = job_reference.location
179
182
 
180
183
  res = client.get_job(project, job_id, location: location)
181
184
  log.debug "load job fetched", id: job_id, state: res.status.state, **job_reference.as_hash(:project_id, :dataset_id, :table_id)
@@ -29,9 +29,6 @@ module Fluent
29
29
  config_param :private_key_path, :string, default: nil
30
30
  config_param :private_key_passphrase, :string, default: 'notasecret', secret: true
31
31
  config_param :json_key, default: nil, secret: true
32
- # The geographic location of the job. Required except for US and EU.
33
- # https://github.com/googleapis/google-api-ruby-client/blob/master/generated/google/apis/bigquery_v2/service.rb#L350
34
- config_param :location, :string, default: nil
35
32
 
36
33
  # see as simple reference
37
34
  # https://github.com/abronte/BigQuery/blob/master/lib/bigquery.rb
@@ -135,7 +132,6 @@ module Fluent
135
132
  private_key_path: @private_key_path, private_key_passphrase: @private_key_passphrase,
136
133
  email: @email,
137
134
  json_key: @json_key,
138
- location: @location,
139
135
  source_format: @source_format,
140
136
  skip_invalid_rows: @skip_invalid_rows,
141
137
  ignore_unknown_values: @ignore_unknown_values,
@@ -65,7 +65,10 @@ class BigQueryLoadOutputTest < Test::Unit::TestCase
65
65
  }
66
66
  }
67
67
  }, upload_source: duck_type(:write, :sync, :rewind), content_type: "application/octet-stream") do
68
- stub!.job_reference.stub!.job_id { "dummy_job_id" }
68
+ stub!.job_reference.stub! do |s|
69
+ s.job_id { "dummy_job_id" }
70
+ s.location { "us" }
71
+ end
69
72
  end
70
73
  end
71
74
 
@@ -118,7 +121,10 @@ class BigQueryLoadOutputTest < Test::Unit::TestCase
118
121
  },
119
122
  job_reference: {project_id: 'yourproject_id', job_id: satisfy { |x| x =~ /fluentd_job_.*/}} ,
120
123
  }, upload_source: duck_type(:write, :sync, :rewind), content_type: "application/octet-stream") do
121
- stub!.job_reference.stub!.job_id { "dummy_job_id" }
124
+ stub!.job_reference.stub! do |s|
125
+ s.job_id { "dummy_job_id" }
126
+ s.location { "us" }
127
+ end
122
128
  end
123
129
  end
124
130
 
@@ -155,10 +161,13 @@ class BigQueryLoadOutputTest < Test::Unit::TestCase
155
161
  }
156
162
  }
157
163
  }, upload_source: duck_type(:write, :sync, :rewind), content_type: "application/octet-stream") do
158
- stub!.job_reference.stub!.job_id { "dummy_job_id" }
164
+ stub!.job_reference.stub! do |s|
165
+ s.job_id { "dummy_job_id" }
166
+ s.location { "us" }
167
+ end
159
168
  end
160
169
 
161
- mock(writer.client).get_job('yourproject_id', 'dummy_job_id', :location=>nil) do
170
+ mock(writer.client).get_job('yourproject_id', 'dummy_job_id', location: "us") do
162
171
  stub! do |s|
163
172
  s.id { 'dummy_job_id' }
164
173
  s.configuration.stub! do |_s|
@@ -238,10 +247,13 @@ class BigQueryLoadOutputTest < Test::Unit::TestCase
238
247
  }
239
248
  }
240
249
  }, upload_source: duck_type(:write, :sync, :rewind), content_type: "application/octet-stream") do
241
- stub!.job_reference.stub!.job_id { "dummy_job_id" }
250
+ stub!.job_reference.stub! do |s|
251
+ s.job_id { "dummy_job_id" }
252
+ s.location { "us" }
253
+ end
242
254
  end
243
255
 
244
- mock(writer.client).get_job('yourproject_id', 'dummy_job_id', :location=>nil) do
256
+ mock(writer.client).get_job('yourproject_id', 'dummy_job_id', location: "us") do
245
257
  stub! do |s|
246
258
  s.id { 'dummy_job_id' }
247
259
  s.configuration.stub! do |_s|
@@ -318,7 +330,10 @@ class BigQueryLoadOutputTest < Test::Unit::TestCase
318
330
  }
319
331
  }
320
332
  }, upload_source: duck_type(:write, :sync, :rewind), content_type: "application/octet-stream") do
321
- stub!.job_reference.stub!.job_id { "dummy_job_id" }
333
+ stub!.job_reference.stub! do |s|
334
+ s.job_id { "dummy_job_id" }
335
+ s.location { "us" }
336
+ end
322
337
  end
323
338
  end
324
339
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fluent-plugin-bigquery
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.2.0
4
+ version: 3.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Naoya Ito
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2024-10-26 00:00:00.000000000 Z
12
+ date: 2025-02-10 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
@@ -191,7 +191,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
191
191
  - !ruby/object:Gem::Version
192
192
  version: '0'
193
193
  requirements: []
194
- rubygems_version: 3.5.11
194
+ rubygems_version: 3.3.27
195
195
  signing_key:
196
196
  specification_version: 4
197
197
  summary: Fluentd plugin to store data on Google BigQuery