volcano-sdk 0.9.4 → 0.10.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.
- checksums.yaml +4 -4
- data/README.md +69 -0
- data/lib/volcano/client.rb +2 -1
- data/lib/volcano/durable.rb +136 -0
- data/lib/volcano/durable_models.rb +143 -0
- data/lib/volcano/generated/lib/volcano-generated/api/databases_api.rb +2 -2
- data/lib/volcano/generated/lib/volcano-generated/api/durable_functions_api.rb +1239 -0
- data/lib/volcano/generated/lib/volcano-generated/api/frontends_api.rb +2 -2
- data/lib/volcano/generated/lib/volcano-generated/api/functions_api.rb +18 -6
- data/lib/volcano/generated/lib/volcano-generated/api/o_auth_authentication_api.rb +2 -2
- data/lib/volcano/generated/lib/volcano-generated/api/projects_api.rb +76 -2
- data/lib/volcano/generated/lib/volcano-generated/models/create_database_request.rb +6 -8
- data/lib/volcano/generated/lib/volcano-generated/models/create_variable_request.rb +11 -1
- data/lib/volcano/generated/lib/volcano-generated/models/durable_execution.rb +358 -0
- data/lib/volcano/generated/lib/volcano-generated/models/durable_execution_error.rb +157 -0
- data/lib/volcano/generated/lib/volcano-generated/models/durable_execution_status.rb +45 -0
- data/lib/volcano/generated/lib/volcano-generated/models/durable_function.rb +479 -0
- data/lib/volcano/generated/lib/volcano-generated/models/durable_function_config.rb +193 -0
- data/lib/volcano/generated/lib/volcano-generated/models/function_kind.rb +40 -0
- data/lib/volcano/generated/lib/volcano-generated/models/function_runtime_option.rb +28 -1
- data/lib/volcano/generated/lib/volcano-generated/models/function_scheduler.rb +11 -1
- data/lib/volcano/generated/lib/volcano-generated/models/list_database_regions200_response_inner.rb +1 -1
- data/lib/volcano/generated/lib/volcano-generated/models/metric_usage_data.rb +1 -1
- data/lib/volcano/generated/lib/volcano-generated/models/paginated_durable_executions.rb +274 -0
- data/lib/volcano/generated/lib/volcano-generated/models/paginated_durable_functions.rb +274 -0
- data/lib/volcano/generated/lib/volcano-generated/models/project_config.rb +23 -1
- data/lib/volcano/generated/lib/volcano-generated/models/project_config_function.rb +47 -2
- data/lib/volcano/generated/lib/volcano-generated/models/project_config_variable.rb +11 -1
- data/lib/volcano/generated/lib/volcano-generated/models/project_deployment_resource.rb +14 -4
- data/lib/volcano/generated/lib/volcano-generated/models/project_health_resource.rb +14 -4
- data/lib/volcano/generated/lib/volcano-generated/models/replace_shared_variables_request.rb +237 -0
- data/lib/volcano/generated/lib/volcano-generated/models/update_variable_request.rb +11 -1
- data/lib/volcano/generated/lib/volcano-generated/models/variable.rb +11 -1
- data/lib/volcano/generated/lib/volcano-generated.rb +10 -0
- data/lib/volcano/generated_transport.rb +2 -1
- data/lib/volcano/generated_transport_durable.rb +50 -0
- data/lib/volcano/generated_transport_support.rb +1 -0
- data/lib/volcano/version.rb +1 -1
- data/lib/volcano.rb +2 -0
- metadata +14 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ee82d4e1a777fcbca79d4ac464ae7ad87d8f0374fb6955cd1e61167a9c82641c
|
|
4
|
+
data.tar.gz: fd76dca669566978d588a0c0eb01c38b17166a621ae43f1a0f44862884083fb8
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4ce4ffb6d72500cfaae2736bede0a7438a1bf079a3c5c2e540ebf3bd737eb2157c46c8e08011b4d93a15deb900daf616fe076c64f3e29c3dfc0c08ba2e80acce
|
|
7
|
+
data.tar.gz: 8486d6ae8e2fb766e918610389ca94eb98d08446d01a5beebb7002b5a44448508a31681da6100a59ab5f62d4d5b0894fca9072ae09a33914d0c45f9d24f32f03
|
data/README.md
CHANGED
|
@@ -495,6 +495,55 @@ Anonymous and service keys do not refresh.
|
|
|
495
495
|
|
|
496
496
|
See the [functions guide](https://github.com/Kong/volcano-sdk-ruby/blob/main/docs/functions.md).
|
|
497
497
|
|
|
498
|
+
### Start and follow a durable execution
|
|
499
|
+
|
|
500
|
+
```ruby
|
|
501
|
+
project_id = "00000000-0000-4000-8000-000000000001"
|
|
502
|
+
handle = client.durable.start(
|
|
503
|
+
"charge-order",
|
|
504
|
+
{ order_id: "order-9" },
|
|
505
|
+
execution_name: "order-9"
|
|
506
|
+
)
|
|
507
|
+
|
|
508
|
+
execution = client.durable.get(project_id, "charge-order", handle.id)
|
|
509
|
+
puts [execution.status, execution.terminal?, execution.result]
|
|
510
|
+
|
|
511
|
+
page = client.durable.list(project_id, "charge-order", status: "running")
|
|
512
|
+
puts [page.total, page.has_more]
|
|
513
|
+
|
|
514
|
+
client.durable.stop(project_id, "charge-order", handle.id)
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
`start` takes a durable function's name or its id and returns a handle, never a
|
|
518
|
+
result: an execution can run for hours, so its result is read back with `get`.
|
|
519
|
+
It uses the same credential `invoke` does — the active user session, then a
|
|
520
|
+
configured service key, then the anonymous key — and is the only durable
|
|
521
|
+
operation an application credential may perform. An `execution_name` makes the
|
|
522
|
+
start idempotent: starting again under the same name returns the execution that
|
|
523
|
+
already exists rather than beginning a second one.
|
|
524
|
+
|
|
525
|
+
`get`, `list`, and `stop` are owner-scoped and require a platform token or a
|
|
526
|
+
configured service key, because an execution is addressed by its id alone. An
|
|
527
|
+
auth-user session from sign-in is not accepted. `get` carries the deeply
|
|
528
|
+
frozen `result` once the execution has succeeded, and `error` when it failed;
|
|
529
|
+
`result_expired` separates a result the platform has discarded from a function
|
|
530
|
+
that returned nothing. `terminal?` reports whether the execution has stopped
|
|
531
|
+
changing, and counts `unknown` — the status the platform writes for an outcome
|
|
532
|
+
it could not determine — as finished. `list` returns one page of executions,
|
|
533
|
+
most recent first, each carrying the status last observed rather than a live
|
|
534
|
+
one. `stop` is accepted rather than awaited: what it returns is the execution
|
|
535
|
+
read back after asking, often still `running`, so poll `get` to see it reach
|
|
536
|
+
`stopped`. Repeating a stop is safe.
|
|
537
|
+
|
|
538
|
+
This gem starts and follows durable executions; it cannot write the durable
|
|
539
|
+
function itself. Checkpointing a handler needs a durable authoring API, and
|
|
540
|
+
there is no Ruby one, so Volcano hosts durable functions on `nodejs22.x`,
|
|
541
|
+
`nodejs24.x`, `python3.13` and `python3.14`. Write the function in JavaScript
|
|
542
|
+
or Python and drive it from Ruby; the operations above are the whole surface a
|
|
543
|
+
caller needs.
|
|
544
|
+
Ruby remains a fully supported runtime for [standard
|
|
545
|
+
functions](https://volcano.dev/platform/functions/overview).
|
|
546
|
+
|
|
498
547
|
### Read project logs
|
|
499
548
|
|
|
500
549
|
```ruby
|
|
@@ -824,6 +873,26 @@ Connection callbacks receive immutable contexts and run outside protocol
|
|
|
824
873
|
processing. Each registration returns an idempotent callable that stops future
|
|
825
874
|
delivery.
|
|
826
875
|
|
|
876
|
+
## Dependencies
|
|
877
|
+
|
|
878
|
+
Installing `volcano-sdk` pulls in eight gems, plus their own transitive
|
|
879
|
+
dependencies:
|
|
880
|
+
|
|
881
|
+
| Gem | Why |
|
|
882
|
+
| ------------------------------------------------------------ | ----------------------------------------------------------------------- |
|
|
883
|
+
| [`typhoeus`](https://rubygems.org/gems/typhoeus) | The HTTP library the generated REST client uses |
|
|
884
|
+
| [`logger`](https://rubygems.org/gems/logger) | Required by that client, and no longer a default gem |
|
|
885
|
+
| [`async`](https://rubygems.org/gems/async) | The reactor realtime runs its connection and delivery on |
|
|
886
|
+
| [`async-http`](https://rubygems.org/gems/async-http) | The endpoint realtime dials |
|
|
887
|
+
| [`async-websocket`](https://rubygems.org/gems/async-websocket) | The realtime transport itself |
|
|
888
|
+
| [`protocol-rack`](https://rubygems.org/gems/protocol-rack) | A requirement of `async-websocket`, pinned here so the version is ours |
|
|
889
|
+
| [`base64`](https://rubygems.org/gems/base64) | Required by the generated client, and no longer a default gem since Ruby 3.4 |
|
|
890
|
+
| [`json`](https://rubygems.org/gems/json) | Request and response encoding for the generated client |
|
|
891
|
+
|
|
892
|
+
There is no optional durable dependency, because this gem starts and follows
|
|
893
|
+
durable executions rather than writing them. See
|
|
894
|
+
[Start and follow a durable execution](#start-and-follow-a-durable-execution).
|
|
895
|
+
|
|
827
896
|
## Generated boundary
|
|
828
897
|
|
|
829
898
|
The internal REST transport is generated from `openapi/openapi.yaml`, which
|
data/lib/volcano/client.rb
CHANGED
|
@@ -12,7 +12,7 @@ module Volcano
|
|
|
12
12
|
end
|
|
13
13
|
private_constant :SessionToken
|
|
14
14
|
|
|
15
|
-
attr_reader :auth, :functions, :logs, :storage, :locks, :realtime
|
|
15
|
+
attr_reader :auth, :functions, :durable, :logs, :storage, :locks, :realtime
|
|
16
16
|
|
|
17
17
|
def initialize(
|
|
18
18
|
anon_key:,
|
|
@@ -112,6 +112,7 @@ module Volcano
|
|
|
112
112
|
def initialize_facades(socket_factory, reconnect_delay)
|
|
113
113
|
@auth = Auth.new(self, @transport, api_url: @api_url)
|
|
114
114
|
@functions = Functions.new(self, @transport, api_url: @api_url)
|
|
115
|
+
@durable = Durable.new(self, @transport)
|
|
115
116
|
@logs = Logs.new(self, @transport)
|
|
116
117
|
@storage = Storage.new(self, @transport, api_url: @api_url, anon_key: @anon_key)
|
|
117
118
|
@locks = Locks.new(self, @transport)
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Volcano
|
|
4
|
+
# Starts and follows executions of deployed durable functions.
|
|
5
|
+
class Durable
|
|
6
|
+
# What the platform accepts as an execution name, and the page size it
|
|
7
|
+
# serves at most. Mirrored from the wire contract so a refusal is the
|
|
8
|
+
# facade's rather than the generated client's.
|
|
9
|
+
EXECUTION_NAME = /\A[A-Za-z0-9._-]{1,255}\z/
|
|
10
|
+
MAX_PAGE_SIZE = 100
|
|
11
|
+
include DurableResponses
|
|
12
|
+
|
|
13
|
+
def initialize(client, transport)
|
|
14
|
+
@client = client
|
|
15
|
+
@transport = transport
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Starts an execution and returns its handle. A durable function is never
|
|
19
|
+
# invoked synchronously: it can outlive any request a caller could hold
|
|
20
|
+
# open, so its result is read back with #get.
|
|
21
|
+
#
|
|
22
|
+
# Starting is the only durable operation an application credential may
|
|
23
|
+
# perform, and it takes the token an invoke takes. Passing an
|
|
24
|
+
# +execution_name+ makes the start idempotent: starting again under the
|
|
25
|
+
# same name returns the execution that already exists rather than
|
|
26
|
+
# beginning a second one.
|
|
27
|
+
def start(function_name, payload = {}, execution_name: nil)
|
|
28
|
+
# A durable function's id is accepted here as well as its name, so the
|
|
29
|
+
# DNS-safe name pattern an invoke checks would reject half the input.
|
|
30
|
+
function_id = identifier(function_name, 'function_name')
|
|
31
|
+
name = execution_name.nil? ? nil : execution_name_argument(execution_name)
|
|
32
|
+
response = Transport.invoke do
|
|
33
|
+
@transport.start_durable_execution_from_application(
|
|
34
|
+
authorization: @client.function_token,
|
|
35
|
+
function_id: function_id, payload: payload.dup, execution_name: name
|
|
36
|
+
)
|
|
37
|
+
end
|
|
38
|
+
durable_execution(Transport.body(response, 202))
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Reads an execution, including its result once it has succeeded.
|
|
42
|
+
#
|
|
43
|
+
# Owner-scoped: an execution is addressed by its id alone and an anon key
|
|
44
|
+
# is held by everyone who loads the page, so this takes the project id and
|
|
45
|
+
# a platform token or service key. An auth-user session from sign-in is
|
|
46
|
+
# not enough. Poll it from a backend, not a browser.
|
|
47
|
+
def get(project_id, function_name, execution_id)
|
|
48
|
+
project, function_id, execution = execution_path(project_id, function_name, execution_id)
|
|
49
|
+
response = Transport.invoke do
|
|
50
|
+
@transport.get_durable_execution(
|
|
51
|
+
authorization: @client.session_token,
|
|
52
|
+
project_id: project, function_id: function_id, execution_id: execution
|
|
53
|
+
)
|
|
54
|
+
end
|
|
55
|
+
durable_execution(Transport.body(response, 200))
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Lists a durable function's executions, most recent first. Each entry
|
|
59
|
+
# carries the status the platform last observed rather than a live one;
|
|
60
|
+
# read a single execution for that. Owner-scoped, like #get.
|
|
61
|
+
def list(project_id, function_name, status: nil, page: nil, limit: nil)
|
|
62
|
+
project = identifier(project_id, 'project_id')
|
|
63
|
+
function_id = identifier(function_name, 'function_name')
|
|
64
|
+
validate_paging(page, limit)
|
|
65
|
+
response = Transport.invoke do
|
|
66
|
+
@transport.list_durable_executions(
|
|
67
|
+
authorization: @client.session_token, project_id: project, function_id: function_id,
|
|
68
|
+
options: { status: status, page: page, limit: limit }.compact
|
|
69
|
+
)
|
|
70
|
+
end
|
|
71
|
+
durable_execution_page(Transport.body(response, 200))
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Asks a running execution to stop. Accepted rather than awaited: what
|
|
75
|
+
# comes back is the execution read after asking, and it often still says
|
|
76
|
+
# +running+, so poll #get to see it reach +stopped+. Completed steps are
|
|
77
|
+
# not undone, and repeating a stop is safe — an execution that has already
|
|
78
|
+
# finished reports the state it settled in. Owner-scoped, like #get.
|
|
79
|
+
def stop(project_id, function_name, execution_id)
|
|
80
|
+
project, function_id, execution = execution_path(project_id, function_name, execution_id)
|
|
81
|
+
response = Transport.invoke do
|
|
82
|
+
@transport.stop_durable_execution(
|
|
83
|
+
authorization: @client.session_token,
|
|
84
|
+
project_id: project, function_id: function_id, execution_id: execution
|
|
85
|
+
)
|
|
86
|
+
end
|
|
87
|
+
durable_execution(Transport.body(response, 200))
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
private
|
|
91
|
+
|
|
92
|
+
def execution_path(project_id, function_name, execution_id)
|
|
93
|
+
[
|
|
94
|
+
identifier(project_id, 'project_id'),
|
|
95
|
+
identifier(function_name, 'function_name'),
|
|
96
|
+
identifier(execution_id, 'execution_id')
|
|
97
|
+
]
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# An empty path segment would address the collection instead of the
|
|
101
|
+
# execution, which is a different request rather than a failed one.
|
|
102
|
+
def identifier(value, field)
|
|
103
|
+
raise ArgumentError, "#{field} must be a non-empty String" unless present_string?(value)
|
|
104
|
+
|
|
105
|
+
value.strip.freeze
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# The generated client validates this header against the same pattern and
|
|
109
|
+
# raises its own message, naming the operation and the option key it knows
|
|
110
|
+
# the header by. Checked here first so the caller reads a message about the
|
|
111
|
+
# argument they passed, the way Functions#invoke does for a function name.
|
|
112
|
+
def execution_name_argument(value)
|
|
113
|
+
name = identifier(value, 'execution_name')
|
|
114
|
+
unless EXECUTION_NAME.match?(name)
|
|
115
|
+
raise ArgumentError,
|
|
116
|
+
'execution_name must be 1-255 characters of letters, numbers, dots, dashes or underscores'
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
name
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# Same reason: the generated client enforces the page and limit bounds and
|
|
123
|
+
# answers with its own vocabulary.
|
|
124
|
+
def validate_paging(page, limit)
|
|
125
|
+
raise ArgumentError, 'page must be a positive Integer' unless page.nil? || positive_integer?(page)
|
|
126
|
+
|
|
127
|
+
return if limit.nil? || (positive_integer?(limit) && limit <= MAX_PAGE_SIZE)
|
|
128
|
+
|
|
129
|
+
raise ArgumentError, "limit must be an Integer between 1 and #{MAX_PAGE_SIZE}"
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def positive_integer?(value)
|
|
133
|
+
value.is_a?(Integer) && value.positive?
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'time'
|
|
4
|
+
|
|
5
|
+
module Volcano
|
|
6
|
+
DURABLE_EXECUTION_ATTRIBUTES = %i[
|
|
7
|
+
id function_id name status region created_at result result_expired error completed_at
|
|
8
|
+
].freeze
|
|
9
|
+
private_constant :DURABLE_EXECUTION_ATTRIBUTES
|
|
10
|
+
|
|
11
|
+
# `unknown` is terminal, and the platform writes it itself for an execution
|
|
12
|
+
# whose outcome it could not determine. Code that switches on status has to
|
|
13
|
+
# treat it as finished, or it reads a finished execution as still running.
|
|
14
|
+
DURABLE_TERMINAL_STATUSES = %w[succeeded failed timed_out stopped unknown].freeze
|
|
15
|
+
private_constant :DURABLE_TERMINAL_STATUSES
|
|
16
|
+
|
|
17
|
+
# Why a failed or timed-out execution ended.
|
|
18
|
+
DurableExecutionError = Data.define(:type, :message) do
|
|
19
|
+
def initialize(type: nil, message: nil)
|
|
20
|
+
super(type: type&.dup&.freeze, message: message&.dup&.freeze)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# A durable execution, as the platform last observed it.
|
|
25
|
+
#
|
|
26
|
+
# `result` is absent while the execution is still running, and absent again
|
|
27
|
+
# once its retention lapses. That is not the same as a function that returned
|
|
28
|
+
# nothing, so read `result_expired` before concluding anything from a missing
|
|
29
|
+
# result.
|
|
30
|
+
DurableExecution = Data.define(*DURABLE_EXECUTION_ATTRIBUTES) do
|
|
31
|
+
def initialize(**attributes)
|
|
32
|
+
unknown = attributes.keys - DURABLE_EXECUTION_ATTRIBUTES
|
|
33
|
+
raise ArgumentError, "unknown keywords: #{unknown.join(', ')}" unless unknown.empty?
|
|
34
|
+
|
|
35
|
+
missing = DURABLE_EXECUTION_ATTRIBUTES.first(6) - attributes.keys
|
|
36
|
+
raise ArgumentError, "missing keywords: #{missing.join(', ')}" unless missing.empty?
|
|
37
|
+
|
|
38
|
+
values = DURABLE_EXECUTION_ATTRIBUTES.to_h do |name|
|
|
39
|
+
[name, immutable_value(attributes[name])]
|
|
40
|
+
end
|
|
41
|
+
super(**values)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Reports whether the execution has stopped changing.
|
|
45
|
+
def terminal?
|
|
46
|
+
DURABLE_TERMINAL_STATUSES.include?(status)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
private
|
|
50
|
+
|
|
51
|
+
# `result` is the function's own JSON, so it is frozen all the way down.
|
|
52
|
+
def immutable_value(value)
|
|
53
|
+
case value
|
|
54
|
+
when Hash then value.to_h { |key, item| [immutable_value(key), immutable_value(item)] }.freeze
|
|
55
|
+
when Array then value.map { |item| immutable_value(item) }.freeze
|
|
56
|
+
when Time, String then value.dup.freeze
|
|
57
|
+
else value
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# One page of a durable function's executions, most recent first.
|
|
63
|
+
DurableExecutionPage = Data.define(:executions, :page, :limit, :total, :has_more) do
|
|
64
|
+
def initialize(executions:, page:, limit:, total:, has_more:)
|
|
65
|
+
super(
|
|
66
|
+
executions: executions.to_a.dup.freeze,
|
|
67
|
+
page: page, limit: limit, total: total, has_more: has_more
|
|
68
|
+
)
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Builds the public durable types from transport payloads.
|
|
73
|
+
module DurableResponses
|
|
74
|
+
INCOMPLETE_EXECUTION = 'Expected a complete durable execution'
|
|
75
|
+
INCOMPLETE_PAGE = 'Expected a complete durable execution page'
|
|
76
|
+
EXECUTION_FIELDS = %w[id function_id name status region].freeze
|
|
77
|
+
private_constant :INCOMPLETE_EXECUTION, :INCOMPLETE_PAGE, :EXECUTION_FIELDS
|
|
78
|
+
|
|
79
|
+
private
|
|
80
|
+
|
|
81
|
+
def durable_execution(payload)
|
|
82
|
+
values = execution_payload(payload)
|
|
83
|
+
DurableExecution.new(
|
|
84
|
+
id: values.fetch('id'), function_id: values.fetch('function_id'),
|
|
85
|
+
name: values.fetch('name'), status: values.fetch('status'),
|
|
86
|
+
region: values.fetch('region'), created_at: parse_time(values.fetch('created_at')),
|
|
87
|
+
result: values['result'], result_expired: values['result_expired'],
|
|
88
|
+
error: execution_error(values['error']), completed_at: parse_time(values['completed_at'])
|
|
89
|
+
)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def execution_payload(payload)
|
|
93
|
+
raise TypeError, INCOMPLETE_EXECUTION unless payload.is_a?(Hash)
|
|
94
|
+
|
|
95
|
+
complete = EXECUTION_FIELDS.all? { |field| present_string?(payload[field]) }
|
|
96
|
+
raise TypeError, INCOMPLETE_EXECUTION unless complete && payload['created_at']
|
|
97
|
+
|
|
98
|
+
payload
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def execution_error(payload)
|
|
102
|
+
return if payload.nil?
|
|
103
|
+
raise TypeError, INCOMPLETE_EXECUTION unless payload.is_a?(Hash)
|
|
104
|
+
|
|
105
|
+
DurableExecutionError.new(type: payload['type'], message: payload['message'])
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def durable_execution_page(payload)
|
|
109
|
+
data, has_more = page_payload(payload)
|
|
110
|
+
DurableExecutionPage.new(
|
|
111
|
+
executions: data.map { |entry| durable_execution(entry) }, has_more: has_more,
|
|
112
|
+
page: count(payload['page']), limit: count(payload['limit']), total: count(payload['total'])
|
|
113
|
+
)
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
# An empty page carries no executions at all rather than an empty array.
|
|
117
|
+
def page_payload(payload)
|
|
118
|
+
raise TypeError, INCOMPLETE_PAGE unless payload.is_a?(Hash)
|
|
119
|
+
|
|
120
|
+
data = payload['data'] || []
|
|
121
|
+
has_more = payload.fetch('has_more', false)
|
|
122
|
+
raise TypeError, INCOMPLETE_PAGE unless data.is_a?(Array) && [true, false].include?(has_more)
|
|
123
|
+
|
|
124
|
+
[data, has_more]
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def count(value)
|
|
128
|
+
return 0 if value.nil?
|
|
129
|
+
raise TypeError, INCOMPLETE_PAGE unless value.is_a?(Integer)
|
|
130
|
+
|
|
131
|
+
value
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def present_string?(value)
|
|
135
|
+
value.is_a?(String) && !value.strip.empty?
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def parse_time(value)
|
|
139
|
+
value.is_a?(String) ? Time.iso8601(value) : value
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
private_constant :DurableResponses
|
|
143
|
+
end
|
|
@@ -428,7 +428,7 @@ module Volcano::Generated
|
|
|
428
428
|
end
|
|
429
429
|
|
|
430
430
|
# List platform-supported regions for database provisioning
|
|
431
|
-
# Returns the regions enabled for database provisioning in this platform environment. This is a public endpoint that doesn't require authentication.
|
|
431
|
+
# Returns the regions enabled for database provisioning in this platform environment. These are the same regions offered for function deployment, and the only values the `region` field of a database accepts. This is a public endpoint that doesn't require authentication.
|
|
432
432
|
# @param [Hash] opts the optional parameters
|
|
433
433
|
# @return [Array<ListDatabaseRegions200ResponseInner>]
|
|
434
434
|
def list_database_regions(opts = {})
|
|
@@ -437,7 +437,7 @@ module Volcano::Generated
|
|
|
437
437
|
end
|
|
438
438
|
|
|
439
439
|
# List platform-supported regions for database provisioning
|
|
440
|
-
# Returns the regions enabled for database provisioning in this platform environment. This is a public endpoint that doesn't require authentication.
|
|
440
|
+
# Returns the regions enabled for database provisioning in this platform environment. These are the same regions offered for function deployment, and the only values the `region` field of a database accepts. This is a public endpoint that doesn't require authentication.
|
|
441
441
|
# @param [Hash] opts the optional parameters
|
|
442
442
|
# @return [Array<(Array<ListDatabaseRegions200ResponseInner>, Integer, Hash)>] Array<ListDatabaseRegions200ResponseInner> data, response status code and response headers
|
|
443
443
|
def list_database_regions_with_http_info(opts = {})
|