workato-connector-sdk 1.1.0 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +3 -2
  3. data/VERSION +1 -0
  4. data/lib/workato/cli/edit_command.rb +3 -1
  5. data/lib/workato/cli/exec_command.rb +103 -17
  6. data/lib/workato/cli/generate_command.rb +2 -2
  7. data/lib/workato/cli/main.rb +17 -10
  8. data/lib/workato/cli/multi_auth_selected_fallback.rb +33 -0
  9. data/lib/workato/cli/oauth2_command.rb +50 -12
  10. data/lib/workato/cli/push_command.rb +2 -2
  11. data/lib/workato/cli/schema_command.rb +2 -2
  12. data/lib/workato/connector/sdk/account_properties.rb +2 -2
  13. data/lib/workato/connector/sdk/action.rb +20 -70
  14. data/lib/workato/connector/sdk/block_invocation_refinements.rb +2 -10
  15. data/lib/workato/connector/sdk/connection.rb +115 -30
  16. data/lib/workato/connector/sdk/connector.rb +71 -81
  17. data/lib/workato/connector/sdk/core.rb +62 -0
  18. data/lib/workato/connector/sdk/dsl/aws.rb +8 -5
  19. data/lib/workato/connector/sdk/dsl/call.rb +1 -1
  20. data/lib/workato/connector/sdk/dsl/csv_package.rb +133 -0
  21. data/lib/workato/connector/sdk/dsl/execution_context.rb +45 -0
  22. data/lib/workato/connector/sdk/dsl/http.rb +1 -1
  23. data/lib/workato/connector/sdk/dsl/reinvoke_after.rb +84 -0
  24. data/lib/workato/connector/sdk/dsl/stream_package.rb +65 -0
  25. data/lib/workato/connector/sdk/dsl/time.rb +0 -14
  26. data/lib/workato/connector/sdk/dsl/workato_package.rb +146 -0
  27. data/lib/workato/connector/sdk/dsl.rb +64 -10
  28. data/lib/workato/connector/sdk/errors.rb +37 -9
  29. data/lib/workato/connector/sdk/lookup_tables.rb +3 -1
  30. data/lib/workato/connector/sdk/operation.rb +33 -10
  31. data/lib/workato/connector/sdk/request.rb +149 -69
  32. data/lib/workato/connector/sdk/schema/field/convertors.rb +2 -2
  33. data/lib/workato/connector/sdk/schema/type/unicode_string.rb +1 -1
  34. data/lib/workato/connector/sdk/schema.rb +12 -8
  35. data/lib/workato/connector/sdk/settings.rb +14 -3
  36. data/lib/workato/connector/sdk/stream.rb +243 -0
  37. data/lib/workato/connector/sdk/streams.rb +71 -0
  38. data/lib/workato/connector/sdk/summarize.rb +2 -2
  39. data/lib/workato/connector/sdk/trigger.rb +23 -15
  40. data/lib/workato/connector/sdk/version.rb +1 -1
  41. data/lib/workato/connector/sdk.rb +21 -47
  42. data/lib/workato/extension/array.rb +2 -0
  43. data/lib/workato/extension/case_sensitive_headers.rb +0 -26
  44. data/lib/workato/extension/content_encoding_decoder.rb +69 -0
  45. data/lib/workato/extension/currency/countries.rb +79 -0
  46. data/lib/workato/extension/currency/countries.yml +18433 -0
  47. data/lib/workato/extension/currency/currencies.rb +55 -0
  48. data/lib/workato/extension/currency/currencies.yml +479 -0
  49. data/lib/workato/extension/currency.rb +73 -5
  50. data/lib/workato/extension/enumerable.rb +2 -2
  51. data/lib/workato/extension/extra_chain_cert.rb +0 -14
  52. data/lib/workato/extension/hash_with_indifferent_access.rb +19 -0
  53. data/lib/workato/extension/metadata_fix_wrap_kw_args.rb +11 -0
  54. data/lib/workato/extension/string.rb +16 -112
  55. data/lib/workato/testing/vcr_encrypted_cassette_serializer.rb +2 -0
  56. data/lib/workato/types/binary.rb +55 -0
  57. data/lib/workato/{connector/sdk → utilities}/xml.rb +4 -4
  58. metadata +61 -64
  59. data/lib/workato/connector/sdk/dsl/workato_code_lib.rb +0 -160
@@ -1,6 +1,8 @@
1
1
  # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
+ using Workato::Extension::HashWithIndifferentAccess
5
+
4
6
  module Workato
5
7
  module Connector
6
8
  module Sdk
@@ -21,15 +23,10 @@ module Workato
21
23
 
22
24
  sig { params(definition: SorbetTypes::SourceHash, settings: SorbetTypes::SettingsHash).void }
23
25
  def initialize(definition, settings = {})
24
- @source = T.let(definition.with_indifferent_access, HashWithIndifferentAccess)
25
- @settings = T.let(settings.with_indifferent_access, HashWithIndifferentAccess)
26
- @connection_source = T.let(@source[:connection] || {}.with_indifferent_access, HashWithIndifferentAccess)
27
- @methods_source = T.let(@source[:methods] || {}.with_indifferent_access, HashWithIndifferentAccess)
28
- end
29
-
30
- sig { params(path: String, params: T::Hash[Symbol, T.untyped]).returns(T.untyped) }
31
- def invoke(path, params = {})
32
- InvokePath.new(path: path, connector: self, params: params).call
26
+ @source = T.let(HashWithIndifferentAccess.wrap(definition), HashWithIndifferentAccess)
27
+ @settings = T.let(HashWithIndifferentAccess.wrap(settings), HashWithIndifferentAccess)
28
+ @connection_source = T.let(HashWithIndifferentAccess.wrap(@source[:connection]), HashWithIndifferentAccess)
29
+ @methods_source = T.let(HashWithIndifferentAccess.wrap(@source[:methods]), HashWithIndifferentAccess)
33
30
  end
34
31
 
35
32
  sig { returns(T.nilable(String)) }
@@ -44,7 +41,8 @@ module Workato
44
41
  actions: source[:actions].presence || {},
45
42
  methods: methods_source,
46
43
  object_definitions: object_definitions,
47
- connection: connection
44
+ connection: connection,
45
+ streams: streams
48
46
  )
49
47
  end
50
48
 
@@ -53,7 +51,8 @@ module Workato
53
51
  @methods = T.let(@methods, T.nilable(MethodsProxy))
54
52
  @methods ||= MethodsProxy.new(
55
53
  methods: methods_source,
56
- connection: connection
54
+ connection: connection,
55
+ streams: streams
57
56
  )
58
57
  end
59
58
 
@@ -77,7 +76,8 @@ module Workato
77
76
  triggers: source[:triggers].presence || {},
78
77
  methods: methods_source,
79
78
  connection: connection,
80
- object_definitions: object_definitions
79
+ object_definitions: object_definitions,
80
+ streams: streams
81
81
  )
82
82
  end
83
83
 
@@ -111,8 +111,34 @@ module Workato
111
111
  )
112
112
  end
113
113
 
114
+ sig { returns(Streams) }
115
+ def streams
116
+ @streams = T.let(@streams, T.nilable(Streams))
117
+ @streams ||= Streams.new(
118
+ streams: streams_sources,
119
+ methods: methods_source,
120
+ connection: connection
121
+ )
122
+ end
123
+
114
124
  private
115
125
 
126
+ sig { returns(HashWithIndifferentAccess) }
127
+ def streams_sources
128
+ @streams_sources = T.let(@streams_sources, T.nilable(HashWithIndifferentAccess))
129
+ return @streams_sources if @streams_sources
130
+
131
+ @streams_sources = HashWithIndifferentAccess.new
132
+ @streams_sources.merge!(source[:streams].presence || {})
133
+ (source[:actions] || {}).values.map do |action|
134
+ @streams_sources.merge!(action[:streams] || {})
135
+ end
136
+ (source[:trigger] || {}).values.map do |trigger|
137
+ @streams_sources.merge!(trigger[:streams] || {})
138
+ end
139
+ @streams_sources
140
+ end
141
+
116
142
  sig { returns(HashWithIndifferentAccess) }
117
143
  attr_reader :methods_source
118
144
 
@@ -131,18 +157,20 @@ module Workato
131
157
  actions: HashWithIndifferentAccess,
132
158
  object_definitions: ObjectDefinitions,
133
159
  methods: HashWithIndifferentAccess,
134
- connection: Connection
160
+ connection: Connection,
161
+ streams: Streams
135
162
  ).void
136
163
  end
137
- def initialize(actions:, object_definitions:, methods:, connection:)
164
+ def initialize(actions:, object_definitions:, methods:, connection:, streams:)
138
165
  @methods = methods
139
166
  @connection = connection
140
167
  @object_definitions = object_definitions
168
+ @streams = streams
141
169
  @actions = T.let({}, T::Hash[T.any(Symbol, String), Action])
142
170
  define_action_methods(actions)
143
171
  end
144
172
 
145
- sig { params(action: T.any(Symbol, String)).returns(T.untyped) }
173
+ sig { params(action: T.any(Symbol, String)).returns(Action) }
146
174
  def [](action)
147
175
  public_send(action)
148
176
  end
@@ -155,6 +183,9 @@ module Workato
155
183
  sig { returns(Connection) }
156
184
  attr_reader :connection
157
185
 
186
+ sig { returns(Streams) }
187
+ attr_reader :streams
188
+
158
189
  sig { returns(ObjectDefinitions) }
159
190
  attr_reader :object_definitions
160
191
 
@@ -166,7 +197,8 @@ module Workato
166
197
  action: definition,
167
198
  object_definitions: object_definitions,
168
199
  methods: methods,
169
- connection: connection
200
+ connection: connection,
201
+ streams: streams
170
202
  )
171
203
  return @actions[action] if input_.nil?
172
204
 
@@ -182,12 +214,14 @@ module Workato
182
214
  sig do
183
215
  params(
184
216
  methods: HashWithIndifferentAccess,
185
- connection: Connection
217
+ connection: Connection,
218
+ streams: Streams
186
219
  ).void
187
220
  end
188
- def initialize(methods:, connection:)
221
+ def initialize(methods:, connection:, streams:)
189
222
  @methods = methods
190
223
  @connection = connection
224
+ @streams = streams
191
225
  @actions = T.let({}, T::Hash[T.any(Symbol, String), Action])
192
226
  define_action_methods
193
227
  end
@@ -200,6 +234,9 @@ module Workato
200
234
  sig { returns(Connection) }
201
235
  attr_reader :connection
202
236
 
237
+ sig { returns(Streams) }
238
+ attr_reader :streams
239
+
203
240
  sig { void }
204
241
  def define_action_methods
205
242
  methods.each do |method, _definition|
@@ -209,7 +246,8 @@ module Workato
209
246
  execute: -> { T.unsafe(self).call(method, *args) }
210
247
  },
211
248
  methods: methods,
212
- connection: connection
249
+ connection: connection,
250
+ streams: streams
213
251
  )
214
252
  T.must(@actions[method]).execute
215
253
  end
@@ -276,17 +314,24 @@ module Workato
276
314
  triggers: HashWithIndifferentAccess,
277
315
  object_definitions: ObjectDefinitions,
278
316
  methods: HashWithIndifferentAccess,
279
- connection: Connection
317
+ connection: Connection,
318
+ streams: Streams
280
319
  ).void
281
320
  end
282
- def initialize(triggers:, object_definitions:, methods:, connection:)
321
+ def initialize(triggers:, object_definitions:, methods:, connection:, streams:)
283
322
  @methods = methods
284
323
  @connection = connection
285
324
  @object_definitions = object_definitions
325
+ @streams = streams
286
326
  @triggers = T.let({}, T::Hash[T.any(Symbol, String), Trigger])
287
327
  define_trigger_methods(triggers)
288
328
  end
289
329
 
330
+ sig { params(trigger: T.any(Symbol, String)).returns(Trigger) }
331
+ def [](trigger)
332
+ public_send(trigger)
333
+ end
334
+
290
335
  private
291
336
 
292
337
  sig { returns(HashWithIndifferentAccess) }
@@ -295,6 +340,9 @@ module Workato
295
340
  sig { returns(Connection) }
296
341
  attr_reader :connection
297
342
 
343
+ sig { returns(Streams) }
344
+ attr_reader :streams
345
+
298
346
  sig { returns(ObjectDefinitions) }
299
347
  attr_reader :object_definitions
300
348
 
@@ -306,7 +354,8 @@ module Workato
306
354
  trigger: definition,
307
355
  object_definitions: object_definitions,
308
356
  methods: methods,
309
- connection: connection
357
+ connection: connection,
358
+ streams: streams
310
359
  )
311
360
 
312
361
  return @triggers[trigger] if input_.nil?
@@ -316,65 +365,6 @@ module Workato
316
365
  end
317
366
  end
318
367
  end
319
-
320
- class InvokePath
321
- extend T::Sig
322
-
323
- sig do
324
- params(
325
- path: String,
326
- connector: Connector,
327
- params: T::Hash[Symbol, T.untyped]
328
- ).void
329
- end
330
- def initialize(path:, connector:, params:)
331
- @path = T.let(path, String)
332
- @connector = T.let(connector, Connector)
333
- @params = T.let(params, T::Hash[Symbol, T.untyped])
334
- end
335
-
336
- sig { returns(T.untyped) }
337
- def call
338
- invoke_path
339
- end
340
-
341
- private
342
-
343
- sig { returns(String) }
344
- attr_reader :path
345
-
346
- sig { returns(Connector) }
347
- attr_reader :connector
348
-
349
- sig { returns(T::Hash[Symbol, T.untyped]) }
350
- attr_reader :params
351
-
352
- sig { returns(T.untyped) }
353
- def invoke_path
354
- methods = path.split('.')
355
- method = methods.pop
356
- raise ArgumentError, 'path is not found' unless method
357
-
358
- object = methods.inject(connector) { |obj, m| obj.public_send(m) }
359
- output = invoke_method(object, method)
360
- if output.respond_to?(:invoke)
361
- invoke_method(output, :invoke)
362
- else
363
- output
364
- end
365
- end
366
-
367
- sig { params(object: T.untyped, method: T.any(Symbol, String)).returns(T.untyped) }
368
- def invoke_method(object, method)
369
- parameters = object.method(method).parameters.reject { |p| p[0] == :block }.map(&:second)
370
- args = params.values_at(*parameters)
371
- if parameters.last == :args
372
- args = args.take(args.length - 1) + Array.wrap(args.last).flatten(1)
373
- end
374
- object.public_send(method, *args)
375
- end
376
- end
377
- private_constant :InvokePath
378
368
  end
379
369
  end
380
370
  end
@@ -0,0 +1,62 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ require 'sorbet-runtime'
5
+ require 'active_support'
6
+ require 'active_support/core_ext/object/deep_dup'
7
+ require 'active_support/core_ext/object/try'
8
+ require 'active_support/core_ext/hash/indifferent_access'
9
+ require 'active_support/core_ext/array/wrap'
10
+ require 'active_support/core_ext/array/access'
11
+ require 'active_support/core_ext/numeric/bytes'
12
+ require 'active_support/core_ext/numeric/conversions'
13
+ require 'active_support/core_ext/numeric/time'
14
+
15
+ module Workato
16
+ module Connector
17
+ module Sdk
18
+ DEFAULT_MASTER_KEY_ENV = 'WORKATO_CONNECTOR_MASTER_KEY'
19
+ DEFAULT_MASTER_KEY_PATH = 'master.key'
20
+
21
+ DEFAULT_CONNECTOR_PATH = 'connector.rb'
22
+
23
+ DEFAULT_SETTINGS_PATH = 'settings.yaml'
24
+ DEFAULT_ENCRYPTED_SETTINGS_PATH = 'settings.yaml.enc'
25
+
26
+ DEFAULT_ACCOUNT_PROPERTIES_PATH = 'account_properties.yaml'
27
+ DEFAULT_ENCRYPTED_ACCOUNT_PROPERTIES_PATH = 'account_properties.yaml.enc'
28
+
29
+ DEFAULT_LOOKUP_TABLES_PATH = 'lookup_tables.yaml'
30
+
31
+ DEFAULT_TIME_ZONE = 'Pacific Time (US & Canada)'
32
+
33
+ DEFAULT_SCHEMAS_PATH = 'workato_schemas.json'
34
+
35
+ WORKATO_API_EMAIL_ENV = 'WORKATO_API_EMAIL'
36
+ WORKATO_API_TOKEN_ENV = 'WORKATO_API_TOKEN'
37
+
38
+ WORKATO_BASE_URL_ENV = 'WORKATO_BASE_URL'
39
+ DEFAULT_WORKATO_BASE_URL = 'https://app.workato.com'
40
+ WORKATO_BASE_URL = T.let(ENV.fetch(WORKATO_BASE_URL_ENV, DEFAULT_WORKATO_BASE_URL), String)
41
+ end
42
+ end
43
+ end
44
+
45
+ require_relative '../../extension/hash_with_indifferent_access'
46
+
47
+ require_relative './errors'
48
+ require_relative './account_properties'
49
+ require_relative './operation'
50
+ require_relative './connection'
51
+ require_relative './stream'
52
+ require_relative './streams'
53
+ require_relative './action'
54
+ require_relative './lookup_tables'
55
+ require_relative './object_definitions'
56
+ require_relative './request'
57
+ require_relative './settings'
58
+ require_relative './summarize'
59
+ require_relative './trigger'
60
+ require_relative './version'
61
+ require_relative './workato_schemas'
62
+ require_relative './connector'
@@ -2,6 +2,9 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require 'aws-sigv4'
5
+ require 'workato/utilities/xml'
6
+
7
+ using Workato::Extension::HashWithIndifferentAccess
5
8
 
6
9
  module Workato
7
10
  module Connector
@@ -13,9 +16,9 @@ module Workato
13
16
  DUMMY_AWS_IAM_EXTERNAL_ID = 'dummy-aws-iam-external-id'
14
17
  DUMMY_AWS_WORKATO_ACCOUNT_ID = 'dummy-aws-workato-account-id'
15
18
 
16
- AMAZON_ROLE_CLIENT_ID = ENV['AMAZON_ROLE_CLIENT_ID']
17
- AMAZON_ROLE_CLIENT_KEY = ENV['AMAZON_ROLE_CLIENT_KEY']
18
- AMAZON_ROLE_CLIENT_SECRET = ENV['AMAZON_ROLE_CLIENT_SECRET']
19
+ AMAZON_ROLE_CLIENT_ID = ENV.fetch('AMAZON_ROLE_CLIENT_ID', nil)
20
+ AMAZON_ROLE_CLIENT_KEY = ENV.fetch('AMAZON_ROLE_CLIENT_KEY', nil)
21
+ AMAZON_ROLE_CLIENT_SECRET = ENV.fetch('AMAZON_ROLE_CLIENT_SECRET', nil)
19
22
 
20
23
  WWW_FORM_CONTENT_TYPE = 'application/x-www-form-urlencoded; charset=utf-8'
21
24
 
@@ -55,7 +58,7 @@ module Workato
55
58
  method: method,
56
59
  path: path,
57
60
  params: params,
58
- headers: (headers || {}).with_indifferent_access,
61
+ headers: HashWithIndifferentAccess.wrap(headers),
59
62
  payload: payload
60
63
  )
61
64
 
@@ -134,7 +137,7 @@ module Workato
134
137
  headers: headers,
135
138
  method: :get
136
139
  )
137
- response = Workato::Connector::Sdk::Xml.parse_xml_to_hash(response.body)
140
+ response = Workato::Utilities::Xml.parse_xml_to_hash(response.body)
138
141
 
139
142
  temp_credentials = response.dig('AssumeRoleResponse', 0, 'AssumeRoleResult', 0, 'Credentials', 0)
140
143
  {
@@ -6,7 +6,7 @@ module Workato
6
6
  module Sdk
7
7
  module Dsl
8
8
  module Call
9
- def call(method, *args)
9
+ ruby2_keywords def call(method, *args)
10
10
  method_proc = @_methods[method]
11
11
 
12
12
  raise UndefinedMethodError, method unless method_proc
@@ -0,0 +1,133 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ require 'csv'
5
+
6
+ module Workato
7
+ module Connector
8
+ module Sdk
9
+ CsvError = Class.new(Sdk::RuntimeError)
10
+
11
+ CsvFormatError = Class.new(CsvError)
12
+
13
+ class CsvFileTooBigError < CsvError
14
+ extend T::Sig
15
+
16
+ sig { returns(Integer) }
17
+ attr_reader :size
18
+
19
+ sig { returns(Integer) }
20
+ attr_reader :max
21
+
22
+ sig { params(size: Integer, max: Integer).void }
23
+ def initialize(size, max)
24
+ super("CSV file is too big. Max allowed: #{max.to_s(:human_size)}, got: #{size.to_s(:human_size)}")
25
+ @size = T.let(size, Integer)
26
+ @max = T.let(max, Integer)
27
+ end
28
+ end
29
+
30
+ class CsvFileTooManyLinesError < CsvError
31
+ extend T::Sig
32
+
33
+ sig { returns(Integer) }
34
+ attr_reader :max
35
+
36
+ sig { params(max: Integer).void }
37
+ def initialize(max)
38
+ super("CSV file has too many lines. Max allowed: #{max}")
39
+ @max = T.let(max, Integer)
40
+ end
41
+ end
42
+
43
+ module Dsl
44
+ class CsvPackage
45
+ extend T::Sig
46
+
47
+ MAX_FILE_SIZE_FOR_PARSE = T.let(30.megabytes, Integer)
48
+ private_constant :MAX_FILE_SIZE_FOR_PARSE
49
+
50
+ MAX_LINES_FOR_PARSE = 65_000
51
+ private_constant :MAX_LINES_FOR_PARSE
52
+
53
+ sig do
54
+ params(
55
+ str: String,
56
+ headers: T.any(T::Boolean, T::Array[String], String),
57
+ col_sep: T.nilable(String),
58
+ row_sep: T.nilable(String),
59
+ quote_char: T.nilable(String),
60
+ skip_blanks: T.nilable(T::Boolean),
61
+ skip_first_line: T::Boolean
62
+ ).returns(
63
+ T::Array[T::Hash[String, T.untyped]]
64
+ )
65
+ end
66
+ def parse(str, headers:, col_sep: nil, row_sep: nil, quote_char: nil, skip_blanks: nil,
67
+ skip_first_line: false)
68
+ if str.bytesize > MAX_FILE_SIZE_FOR_PARSE
69
+ raise CsvFileTooBigError.new(str.bytesize, MAX_FILE_SIZE_FOR_PARSE)
70
+ end
71
+
72
+ index = 0
73
+ options = { col_sep: col_sep, row_sep: row_sep, quote_char: quote_char, headers: headers,
74
+ skip_blanks: skip_blanks }.compact
75
+ Enumerator.new do |consumer|
76
+ CSV.parse(str, **options) do |row|
77
+ if index.zero? && skip_first_line
78
+ index += 1
79
+ next
80
+ end
81
+ if index == MAX_LINES_FOR_PARSE
82
+ raise CsvFileTooManyLinesError, MAX_LINES_FOR_PARSE
83
+ end
84
+
85
+ index += 1
86
+ consumer.yield(T.cast(row, CSV::Row).to_hash)
87
+ end
88
+ end.to_a
89
+ rescue CSV::MalformedCSVError => e
90
+ raise CsvFormatError, e
91
+ rescue ArgumentError => e
92
+ raise Sdk::RuntimeError, e.message
93
+ end
94
+
95
+ sig do
96
+ params(
97
+ str: T.nilable(String),
98
+ headers: T.nilable(T::Array[String]),
99
+ col_sep: T.nilable(String),
100
+ row_sep: T.nilable(String),
101
+ quote_char: T.nilable(String),
102
+ force_quotes: T.nilable(T::Boolean),
103
+ blk: T.proc.params(csv: CSV).void
104
+ ).returns(
105
+ String
106
+ )
107
+ end
108
+ def generate(str = nil, headers: nil, col_sep: nil, row_sep: nil, quote_char: nil, force_quotes: nil, &blk)
109
+ options = { col_sep: col_sep, row_sep: row_sep, quote_char: quote_char, headers: headers,
110
+ force_quotes: force_quotes }.compact
111
+ options[:write_headers] = options[:headers].present?
112
+
113
+ ::CSV.generate(str || String.new, **options, &blk)
114
+ rescue ArgumentError => e
115
+ raise Sdk::RuntimeError, e.message
116
+ end
117
+
118
+ private
119
+
120
+ T::Sig::WithoutRuntime.sig { params(symbol: T.any(String, Symbol), _args: T.untyped).void }
121
+ def method_missing(symbol, *_args)
122
+ raise UndefinedStdLibMethodError.new(symbol.to_s, 'workato.csv')
123
+ end
124
+
125
+ T::Sig::WithoutRuntime.sig { params(_args: T.untyped).returns(T::Boolean) }
126
+ def respond_to_missing?(*_args)
127
+ false
128
+ end
129
+ end
130
+ end
131
+ end
132
+ end
133
+ end
@@ -0,0 +1,45 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ require 'securerandom'
5
+ require 'active_support/core_ext/class/attribute'
6
+
7
+ module Workato
8
+ module Connector
9
+ module Sdk
10
+ module Dsl
11
+ module ExecutionContext
12
+ extend T::Sig
13
+ extend T::Helpers
14
+ extend ActiveSupport::Concern
15
+
16
+ included do
17
+ T.bind(self, Class)
18
+
19
+ # encrypted safe recipe_id
20
+ class_attribute :recipe_id, instance_predicate: false, default: SecureRandom.hex(32)
21
+ end
22
+
23
+ sig { returns(T::Hash[Symbol, T.untyped]) }
24
+ def execution_context
25
+ @execution_context ||= {
26
+ recipe_id: recipe_id
27
+ }.compact
28
+ end
29
+
30
+ # mock unencrypted recipe_id for testing only
31
+ def recipe_id!
32
+ recipe_id.reverse
33
+ end
34
+
35
+ module ClassMethods
36
+ # mock unencrypted recipe_id for testing only
37
+ def recipe_id!
38
+ T.unsafe(self).recipe_id.reverse
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -53,7 +53,7 @@ module Workato
53
53
  exception = nil
54
54
  begin
55
55
  response = request.execute!
56
- rescue RequestError, RuntimeError => e
56
+ rescue StandardError => e
57
57
  exception = e.to_s
58
58
  end
59
59
  result[PARALLEL_SUCCESS_INDEX] &&= exception.nil?
@@ -0,0 +1,84 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module Workato
5
+ module Connector
6
+ module Sdk
7
+ module Dsl
8
+ module ReinvokeAfter
9
+ extend T::Sig
10
+
11
+ sig do
12
+ params(
13
+ continue: T::Hash[T.untyped, T.untyped],
14
+ temp_output: T.nilable(T::Hash[T.untyped, T.untyped])
15
+ ).void
16
+ end
17
+ def checkpoint!(continue:, temp_output: nil)
18
+ # no-op
19
+ end
20
+
21
+ sig do
22
+ params(
23
+ seconds: T.any(Integer, Float),
24
+ continue: T::Hash[T.untyped, T.untyped],
25
+ temp_output: T.nilable(T::Hash[T.untyped, T.untyped])
26
+ ).void
27
+ end
28
+ def reinvoke_after(seconds:, continue:, temp_output: nil) # rubocop:disable Lint/UnusedMethodArgument
29
+ Kernel.throw REINVOKE_AFTER_SIGNAL, ReinvokeParams.new(
30
+ seconds: seconds,
31
+ continue: continue
32
+ )
33
+ end
34
+
35
+ private
36
+
37
+ MAX_REINVOKES = 5
38
+ private_constant :MAX_REINVOKES
39
+
40
+ REINVOKE_AFTER_SIGNAL = :reinvoke_after
41
+ private_constant :REINVOKE_AFTER_SIGNAL
42
+
43
+ class ReinvokeParams < T::Struct
44
+ prop :seconds, T.any(Float, Integer)
45
+ prop :continue, T::Hash[T.untyped, T.untyped]
46
+ end
47
+ private_constant :ReinvokeParams
48
+
49
+ sig { params(continue: T::Hash[T.any(Symbol, String), T.untyped], _blk: Proc).returns(T.untyped) }
50
+ def loop_reinvoke_after(continue, &_blk)
51
+ reinvokes_remaining = T.let(reinvoke_limit, Integer)
52
+
53
+ Kernel.loop do
54
+ reinvoke_after = Kernel.catch(REINVOKE_AFTER_SIGNAL) do
55
+ return yield(continue)
56
+ end
57
+
58
+ if reinvokes_remaining.zero?
59
+ Kernel.raise "Max number of reinvokes on SDK Gem reached. Current limit is #{reinvoke_limit}"
60
+ end
61
+
62
+ reinvokes_remaining -= 1
63
+
64
+ reinvoke_after = T.cast(reinvoke_after, ReinvokeParams)
65
+ reinvoke_sleep(reinvoke_after.seconds)
66
+ continue = reinvoke_after.continue
67
+ end
68
+ end
69
+
70
+ sig { params(seconds: T.any(Float, Integer)).void }
71
+ def reinvoke_sleep(seconds)
72
+ Kernel.sleep((ENV['WAIT_REINVOKE_AFTER'].presence || seconds).to_f)
73
+ end
74
+
75
+ sig { returns(Integer) }
76
+ def reinvoke_limit
77
+ @reinvoke_limit = T.let(@reinvoke_limit, T.nilable(Integer))
78
+ @reinvoke_limit ||= (ENV['MAX_REINVOKES'].presence || MAX_REINVOKES).to_i
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end