google-cloud-tasks 0.5.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (26) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/lib/google/cloud/tasks/v2/cloud_tasks_client.rb +1254 -0
  4. data/lib/google/cloud/tasks/v2/cloud_tasks_client_config.json +106 -0
  5. data/lib/google/cloud/tasks/v2/cloudtasks_pb.rb +99 -0
  6. data/lib/google/cloud/tasks/v2/cloudtasks_services_pb.rb +200 -0
  7. data/lib/google/cloud/tasks/v2/credentials.rb +41 -0
  8. data/lib/google/cloud/tasks/v2/doc/google/cloud/tasks/v2/cloudtasks.rb +340 -0
  9. data/lib/google/cloud/tasks/v2/doc/google/cloud/tasks/v2/queue.rb +333 -0
  10. data/lib/google/cloud/tasks/v2/doc/google/cloud/tasks/v2/target.rb +270 -0
  11. data/lib/google/cloud/tasks/v2/doc/google/cloud/tasks/v2/task.rb +170 -0
  12. data/lib/google/cloud/tasks/v2/doc/google/iam/v1/iam_policy.rb +63 -0
  13. data/lib/google/cloud/tasks/v2/doc/google/iam/v1/policy.rb +104 -0
  14. data/lib/google/cloud/tasks/v2/doc/google/protobuf/any.rb +130 -0
  15. data/lib/google/cloud/tasks/v2/doc/google/protobuf/duration.rb +91 -0
  16. data/lib/google/cloud/tasks/v2/doc/google/protobuf/empty.rb +29 -0
  17. data/lib/google/cloud/tasks/v2/doc/google/protobuf/field_mask.rb +230 -0
  18. data/lib/google/cloud/tasks/v2/doc/google/protobuf/timestamp.rb +109 -0
  19. data/lib/google/cloud/tasks/v2/doc/google/rpc/status.rb +87 -0
  20. data/lib/google/cloud/tasks/v2/helpers.rb +56 -0
  21. data/lib/google/cloud/tasks/v2/queue_pb.rb +51 -0
  22. data/lib/google/cloud/tasks/v2/target_pb.rb +44 -0
  23. data/lib/google/cloud/tasks/v2/task_pb.rb +50 -0
  24. data/lib/google/cloud/tasks/v2.rb +139 -0
  25. data/lib/google/cloud/tasks.rb +2 -2
  26. metadata +24 -2
@@ -0,0 +1,106 @@
1
+ {
2
+ "interfaces": {
3
+ "google.cloud.tasks.v2.CloudTasks": {
4
+ "retry_codes": {
5
+ "idempotent": [
6
+ "DEADLINE_EXCEEDED",
7
+ "UNAVAILABLE"
8
+ ],
9
+ "non_idempotent": []
10
+ },
11
+ "retry_params": {
12
+ "default": {
13
+ "initial_retry_delay_millis": 100,
14
+ "retry_delay_multiplier": 1.3,
15
+ "max_retry_delay_millis": 60000,
16
+ "initial_rpc_timeout_millis": 20000,
17
+ "rpc_timeout_multiplier": 1.0,
18
+ "max_rpc_timeout_millis": 20000,
19
+ "total_timeout_millis": 600000
20
+ }
21
+ },
22
+ "methods": {
23
+ "ListQueues": {
24
+ "timeout_millis": 15000,
25
+ "retry_codes_name": "idempotent",
26
+ "retry_params_name": "default"
27
+ },
28
+ "GetQueue": {
29
+ "timeout_millis": 10000,
30
+ "retry_codes_name": "idempotent",
31
+ "retry_params_name": "default"
32
+ },
33
+ "CreateQueue": {
34
+ "timeout_millis": 10000,
35
+ "retry_codes_name": "non_idempotent",
36
+ "retry_params_name": "default"
37
+ },
38
+ "UpdateQueue": {
39
+ "timeout_millis": 10000,
40
+ "retry_codes_name": "non_idempotent",
41
+ "retry_params_name": "default"
42
+ },
43
+ "DeleteQueue": {
44
+ "timeout_millis": 10000,
45
+ "retry_codes_name": "idempotent",
46
+ "retry_params_name": "default"
47
+ },
48
+ "PurgeQueue": {
49
+ "timeout_millis": 10000,
50
+ "retry_codes_name": "non_idempotent",
51
+ "retry_params_name": "default"
52
+ },
53
+ "PauseQueue": {
54
+ "timeout_millis": 10000,
55
+ "retry_codes_name": "non_idempotent",
56
+ "retry_params_name": "default"
57
+ },
58
+ "ResumeQueue": {
59
+ "timeout_millis": 10000,
60
+ "retry_codes_name": "non_idempotent",
61
+ "retry_params_name": "default"
62
+ },
63
+ "GetIamPolicy": {
64
+ "timeout_millis": 10000,
65
+ "retry_codes_name": "idempotent",
66
+ "retry_params_name": "default"
67
+ },
68
+ "SetIamPolicy": {
69
+ "timeout_millis": 10000,
70
+ "retry_codes_name": "non_idempotent",
71
+ "retry_params_name": "default"
72
+ },
73
+ "TestIamPermissions": {
74
+ "timeout_millis": 10000,
75
+ "retry_codes_name": "idempotent",
76
+ "retry_params_name": "default"
77
+ },
78
+ "ListTasks": {
79
+ "timeout_millis": 10000,
80
+ "retry_codes_name": "idempotent",
81
+ "retry_params_name": "default"
82
+ },
83
+ "GetTask": {
84
+ "timeout_millis": 10000,
85
+ "retry_codes_name": "idempotent",
86
+ "retry_params_name": "default"
87
+ },
88
+ "CreateTask": {
89
+ "timeout_millis": 10000,
90
+ "retry_codes_name": "non_idempotent",
91
+ "retry_params_name": "default"
92
+ },
93
+ "DeleteTask": {
94
+ "timeout_millis": 10000,
95
+ "retry_codes_name": "idempotent",
96
+ "retry_params_name": "default"
97
+ },
98
+ "RunTask": {
99
+ "timeout_millis": 10000,
100
+ "retry_codes_name": "non_idempotent",
101
+ "retry_params_name": "default"
102
+ }
103
+ }
104
+ }
105
+ }
106
+ }
@@ -0,0 +1,99 @@
1
+ # Generated by the protocol buffer compiler. DO NOT EDIT!
2
+ # source: google/cloud/tasks/v2/cloudtasks.proto
3
+
4
+
5
+ require 'google/protobuf'
6
+
7
+ require 'google/api/annotations_pb'
8
+ require 'google/protobuf/empty_pb'
9
+ require 'google/protobuf/field_mask_pb'
10
+ require 'google/cloud/tasks/v2/task_pb'
11
+ require 'google/cloud/tasks/v2/queue_pb'
12
+ require 'google/iam/v1/iam_policy_pb'
13
+ require 'google/iam/v1/policy_pb'
14
+ require 'google/rpc/code_pb'
15
+ Google::Protobuf::DescriptorPool.generated_pool.build do
16
+ add_message "google.cloud.tasks.v2.ListQueuesRequest" do
17
+ optional :parent, :string, 1
18
+ optional :filter, :string, 2
19
+ optional :page_size, :int32, 3
20
+ optional :page_token, :string, 4
21
+ end
22
+ add_message "google.cloud.tasks.v2.ListQueuesResponse" do
23
+ repeated :queues, :message, 1, "google.cloud.tasks.v2.Queue"
24
+ optional :next_page_token, :string, 2
25
+ end
26
+ add_message "google.cloud.tasks.v2.GetQueueRequest" do
27
+ optional :name, :string, 1
28
+ end
29
+ add_message "google.cloud.tasks.v2.CreateQueueRequest" do
30
+ optional :parent, :string, 1
31
+ optional :queue, :message, 2, "google.cloud.tasks.v2.Queue"
32
+ end
33
+ add_message "google.cloud.tasks.v2.UpdateQueueRequest" do
34
+ optional :queue, :message, 1, "google.cloud.tasks.v2.Queue"
35
+ optional :update_mask, :message, 2, "google.protobuf.FieldMask"
36
+ end
37
+ add_message "google.cloud.tasks.v2.DeleteQueueRequest" do
38
+ optional :name, :string, 1
39
+ end
40
+ add_message "google.cloud.tasks.v2.PurgeQueueRequest" do
41
+ optional :name, :string, 1
42
+ end
43
+ add_message "google.cloud.tasks.v2.PauseQueueRequest" do
44
+ optional :name, :string, 1
45
+ end
46
+ add_message "google.cloud.tasks.v2.ResumeQueueRequest" do
47
+ optional :name, :string, 1
48
+ end
49
+ add_message "google.cloud.tasks.v2.ListTasksRequest" do
50
+ optional :parent, :string, 1
51
+ optional :response_view, :enum, 2, "google.cloud.tasks.v2.Task.View"
52
+ optional :page_size, :int32, 3
53
+ optional :page_token, :string, 4
54
+ end
55
+ add_message "google.cloud.tasks.v2.ListTasksResponse" do
56
+ repeated :tasks, :message, 1, "google.cloud.tasks.v2.Task"
57
+ optional :next_page_token, :string, 2
58
+ end
59
+ add_message "google.cloud.tasks.v2.GetTaskRequest" do
60
+ optional :name, :string, 1
61
+ optional :response_view, :enum, 2, "google.cloud.tasks.v2.Task.View"
62
+ end
63
+ add_message "google.cloud.tasks.v2.CreateTaskRequest" do
64
+ optional :parent, :string, 1
65
+ optional :task, :message, 2, "google.cloud.tasks.v2.Task"
66
+ optional :response_view, :enum, 3, "google.cloud.tasks.v2.Task.View"
67
+ end
68
+ add_message "google.cloud.tasks.v2.DeleteTaskRequest" do
69
+ optional :name, :string, 1
70
+ end
71
+ add_message "google.cloud.tasks.v2.RunTaskRequest" do
72
+ optional :name, :string, 1
73
+ optional :response_view, :enum, 2, "google.cloud.tasks.v2.Task.View"
74
+ end
75
+ end
76
+
77
+ module Google
78
+ module Cloud
79
+ module Tasks
80
+ module V2
81
+ ListQueuesRequest = Google::Protobuf::DescriptorPool.generated_pool.lookup("google.cloud.tasks.v2.ListQueuesRequest").msgclass
82
+ ListQueuesResponse = Google::Protobuf::DescriptorPool.generated_pool.lookup("google.cloud.tasks.v2.ListQueuesResponse").msgclass
83
+ GetQueueRequest = Google::Protobuf::DescriptorPool.generated_pool.lookup("google.cloud.tasks.v2.GetQueueRequest").msgclass
84
+ CreateQueueRequest = Google::Protobuf::DescriptorPool.generated_pool.lookup("google.cloud.tasks.v2.CreateQueueRequest").msgclass
85
+ UpdateQueueRequest = Google::Protobuf::DescriptorPool.generated_pool.lookup("google.cloud.tasks.v2.UpdateQueueRequest").msgclass
86
+ DeleteQueueRequest = Google::Protobuf::DescriptorPool.generated_pool.lookup("google.cloud.tasks.v2.DeleteQueueRequest").msgclass
87
+ PurgeQueueRequest = Google::Protobuf::DescriptorPool.generated_pool.lookup("google.cloud.tasks.v2.PurgeQueueRequest").msgclass
88
+ PauseQueueRequest = Google::Protobuf::DescriptorPool.generated_pool.lookup("google.cloud.tasks.v2.PauseQueueRequest").msgclass
89
+ ResumeQueueRequest = Google::Protobuf::DescriptorPool.generated_pool.lookup("google.cloud.tasks.v2.ResumeQueueRequest").msgclass
90
+ ListTasksRequest = Google::Protobuf::DescriptorPool.generated_pool.lookup("google.cloud.tasks.v2.ListTasksRequest").msgclass
91
+ ListTasksResponse = Google::Protobuf::DescriptorPool.generated_pool.lookup("google.cloud.tasks.v2.ListTasksResponse").msgclass
92
+ GetTaskRequest = Google::Protobuf::DescriptorPool.generated_pool.lookup("google.cloud.tasks.v2.GetTaskRequest").msgclass
93
+ CreateTaskRequest = Google::Protobuf::DescriptorPool.generated_pool.lookup("google.cloud.tasks.v2.CreateTaskRequest").msgclass
94
+ DeleteTaskRequest = Google::Protobuf::DescriptorPool.generated_pool.lookup("google.cloud.tasks.v2.DeleteTaskRequest").msgclass
95
+ RunTaskRequest = Google::Protobuf::DescriptorPool.generated_pool.lookup("google.cloud.tasks.v2.RunTaskRequest").msgclass
96
+ end
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,200 @@
1
+ # Generated by the protocol buffer compiler. DO NOT EDIT!
2
+ # Source: google/cloud/tasks/v2/cloudtasks.proto for package 'google.cloud.tasks.v2'
3
+ # Original file comments:
4
+ # Copyright 2019 Google LLC.
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+ #
19
+
20
+
21
+ require 'grpc'
22
+ require 'google/cloud/tasks/v2/cloudtasks_pb'
23
+
24
+ module Google
25
+ module Cloud
26
+ module Tasks
27
+ module V2
28
+ module CloudTasks
29
+ # Cloud Tasks allows developers to manage the execution of background
30
+ # work in their applications.
31
+ class Service
32
+
33
+ include GRPC::GenericService
34
+
35
+ self.marshal_class_method = :encode
36
+ self.unmarshal_class_method = :decode
37
+ self.service_name = 'google.cloud.tasks.v2.CloudTasks'
38
+
39
+ # Lists queues.
40
+ #
41
+ # Queues are returned in lexicographical order.
42
+ rpc :ListQueues, ListQueuesRequest, ListQueuesResponse
43
+ # Gets a queue.
44
+ rpc :GetQueue, GetQueueRequest, Queue
45
+ # Creates a queue.
46
+ #
47
+ # Queues created with this method allow tasks to live for a maximum of 31
48
+ # days. After a task is 31 days old, the task will be deleted regardless of whether
49
+ # it was dispatched or not.
50
+ #
51
+ # WARNING: Using this method may have unintended side effects if you are
52
+ # using an App Engine `queue.yaml` or `queue.xml` file to manage your queues.
53
+ # Read
54
+ # [Overview of Queue Management and queue.yaml](https://cloud.google.com/tasks/docs/queue-yaml)
55
+ # before using this method.
56
+ rpc :CreateQueue, CreateQueueRequest, Queue
57
+ # Updates a queue.
58
+ #
59
+ # This method creates the queue if it does not exist and updates
60
+ # the queue if it does exist.
61
+ #
62
+ # Queues created with this method allow tasks to live for a maximum of 31
63
+ # days. After a task is 31 days old, the task will be deleted regardless of whether
64
+ # it was dispatched or not.
65
+ #
66
+ # WARNING: Using this method may have unintended side effects if you are
67
+ # using an App Engine `queue.yaml` or `queue.xml` file to manage your queues.
68
+ # Read
69
+ # [Overview of Queue Management and queue.yaml](https://cloud.google.com/tasks/docs/queue-yaml)
70
+ # before using this method.
71
+ rpc :UpdateQueue, UpdateQueueRequest, Queue
72
+ # Deletes a queue.
73
+ #
74
+ # This command will delete the queue even if it has tasks in it.
75
+ #
76
+ # Note: If you delete a queue, a queue with the same name can't be created
77
+ # for 7 days.
78
+ #
79
+ # WARNING: Using this method may have unintended side effects if you are
80
+ # using an App Engine `queue.yaml` or `queue.xml` file to manage your queues.
81
+ # Read
82
+ # [Overview of Queue Management and queue.yaml](https://cloud.google.com/tasks/docs/queue-yaml)
83
+ # before using this method.
84
+ rpc :DeleteQueue, DeleteQueueRequest, Google::Protobuf::Empty
85
+ # Purges a queue by deleting all of its tasks.
86
+ #
87
+ # All tasks created before this method is called are permanently deleted.
88
+ #
89
+ # Purge operations can take up to one minute to take effect. Tasks
90
+ # might be dispatched before the purge takes effect. A purge is irreversible.
91
+ rpc :PurgeQueue, PurgeQueueRequest, Queue
92
+ # Pauses the queue.
93
+ #
94
+ # If a queue is paused then the system will stop dispatching tasks
95
+ # until the queue is resumed via
96
+ # [ResumeQueue][google.cloud.tasks.v2.CloudTasks.ResumeQueue]. Tasks can still be added
97
+ # when the queue is paused. A queue is paused if its
98
+ # [state][google.cloud.tasks.v2.Queue.state] is [PAUSED][google.cloud.tasks.v2.Queue.State.PAUSED].
99
+ rpc :PauseQueue, PauseQueueRequest, Queue
100
+ # Resume a queue.
101
+ #
102
+ # This method resumes a queue after it has been
103
+ # [PAUSED][google.cloud.tasks.v2.Queue.State.PAUSED] or
104
+ # [DISABLED][google.cloud.tasks.v2.Queue.State.DISABLED]. The state of a queue is stored
105
+ # in the queue's [state][google.cloud.tasks.v2.Queue.state]; after calling this method it
106
+ # will be set to [RUNNING][google.cloud.tasks.v2.Queue.State.RUNNING].
107
+ #
108
+ # WARNING: Resuming many high-QPS queues at the same time can
109
+ # lead to target overloading. If you are resuming high-QPS
110
+ # queues, follow the 500/50/5 pattern described in
111
+ # [Managing Cloud Tasks Scaling Risks](https://cloud.google.com/tasks/docs/manage-cloud-task-scaling).
112
+ rpc :ResumeQueue, ResumeQueueRequest, Queue
113
+ # Gets the access control policy for a [Queue][google.cloud.tasks.v2.Queue].
114
+ # Returns an empty policy if the resource exists and does not have a policy
115
+ # set.
116
+ #
117
+ # Authorization requires the following
118
+ # [Google IAM](https://cloud.google.com/iam) permission on the specified
119
+ # resource parent:
120
+ #
121
+ # * `cloudtasks.queues.getIamPolicy`
122
+ rpc :GetIamPolicy, Google::Iam::V1::GetIamPolicyRequest, Google::Iam::V1::Policy
123
+ # Sets the access control policy for a [Queue][google.cloud.tasks.v2.Queue]. Replaces any existing
124
+ # policy.
125
+ #
126
+ # Note: The Cloud Console does not check queue-level IAM permissions yet.
127
+ # Project-level permissions are required to use the Cloud Console.
128
+ #
129
+ # Authorization requires the following
130
+ # [Google IAM](https://cloud.google.com/iam) permission on the specified
131
+ # resource parent:
132
+ #
133
+ # * `cloudtasks.queues.setIamPolicy`
134
+ rpc :SetIamPolicy, Google::Iam::V1::SetIamPolicyRequest, Google::Iam::V1::Policy
135
+ # Returns permissions that a caller has on a [Queue][google.cloud.tasks.v2.Queue].
136
+ # If the resource does not exist, this will return an empty set of
137
+ # permissions, not a [NOT_FOUND][google.rpc.Code.NOT_FOUND] error.
138
+ #
139
+ # Note: This operation is designed to be used for building permission-aware
140
+ # UIs and command-line tools, not for authorization checking. This operation
141
+ # may "fail open" without warning.
142
+ rpc :TestIamPermissions, Google::Iam::V1::TestIamPermissionsRequest, Google::Iam::V1::TestIamPermissionsResponse
143
+ # Lists the tasks in a queue.
144
+ #
145
+ # By default, only the [BASIC][google.cloud.tasks.v2.Task.View.BASIC] view is retrieved
146
+ # due to performance considerations;
147
+ # [response_view][google.cloud.tasks.v2.ListTasksRequest.response_view] controls the
148
+ # subset of information which is returned.
149
+ #
150
+ # The tasks may be returned in any order. The ordering may change at any
151
+ # time.
152
+ rpc :ListTasks, ListTasksRequest, ListTasksResponse
153
+ # Gets a task.
154
+ rpc :GetTask, GetTaskRequest, Task
155
+ # Creates a task and adds it to a queue.
156
+ #
157
+ # Tasks cannot be updated after creation; there is no UpdateTask command.
158
+ #
159
+ # * For [App Engine queues][google.cloud.tasks.v2.AppEngineHttpQueue], the maximum task size is
160
+ # 100KB.
161
+ rpc :CreateTask, CreateTaskRequest, Task
162
+ # Deletes a task.
163
+ #
164
+ # A task can be deleted if it is scheduled or dispatched. A task
165
+ # cannot be deleted if it has executed successfully or permanently
166
+ # failed.
167
+ rpc :DeleteTask, DeleteTaskRequest, Google::Protobuf::Empty
168
+ # Forces a task to run now.
169
+ #
170
+ # When this method is called, Cloud Tasks will dispatch the task, even if
171
+ # the task is already running, the queue has reached its [RateLimits][google.cloud.tasks.v2.RateLimits] or
172
+ # is [PAUSED][google.cloud.tasks.v2.Queue.State.PAUSED].
173
+ #
174
+ # This command is meant to be used for manual debugging. For
175
+ # example, [RunTask][google.cloud.tasks.v2.CloudTasks.RunTask] can be used to retry a failed
176
+ # task after a fix has been made or to manually force a task to be
177
+ # dispatched now.
178
+ #
179
+ # The dispatched task is returned. That is, the task that is returned
180
+ # contains the [status][Task.status] after the task is dispatched but
181
+ # before the task is received by its target.
182
+ #
183
+ # If Cloud Tasks receives a successful response from the task's
184
+ # target, then the task will be deleted; otherwise the task's
185
+ # [schedule_time][google.cloud.tasks.v2.Task.schedule_time] will be reset to the time that
186
+ # [RunTask][google.cloud.tasks.v2.CloudTasks.RunTask] was called plus the retry delay specified
187
+ # in the queue's [RetryConfig][google.cloud.tasks.v2.RetryConfig].
188
+ #
189
+ # [RunTask][google.cloud.tasks.v2.CloudTasks.RunTask] returns
190
+ # [NOT_FOUND][google.rpc.Code.NOT_FOUND] when it is called on a
191
+ # task that has already succeeded or permanently failed.
192
+ rpc :RunTask, RunTaskRequest, Task
193
+ end
194
+
195
+ Stub = Service.rpc_stub_class
196
+ end
197
+ end
198
+ end
199
+ end
200
+ end
@@ -0,0 +1,41 @@
1
+ # Copyright 2019 Google LLC
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # https://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+
16
+ require "googleauth"
17
+
18
+ module Google
19
+ module Cloud
20
+ module Tasks
21
+ module V2
22
+ class Credentials < Google::Auth::Credentials
23
+ SCOPE = [
24
+ "https://www.googleapis.com/auth/cloud-platform"
25
+ ].freeze
26
+ PATH_ENV_VARS = %w(TASKS_CREDENTIALS
27
+ TASKS_KEYFILE
28
+ GOOGLE_CLOUD_CREDENTIALS
29
+ GOOGLE_CLOUD_KEYFILE
30
+ GCLOUD_KEYFILE)
31
+ JSON_ENV_VARS = %w(TASKS_CREDENTIALS_JSON
32
+ TASKS_KEYFILE_JSON
33
+ GOOGLE_CLOUD_CREDENTIALS_JSON
34
+ GOOGLE_CLOUD_KEYFILE_JSON
35
+ GCLOUD_KEYFILE_JSON)
36
+ DEFAULT_PATHS = ["~/.config/gcloud/application_default_credentials.json"]
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end