workato-connector-sdk 1.1.0 → 1.3.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 (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