-
Notifications
You must be signed in to change notification settings - Fork 6
Add support for Cloud Tasks #282
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,7 @@ | ||
## 0.10.0 | ||
|
||
- Add support for Cloud Tasks | ||
|
||
## 0.9.0 | ||
|
||
- Support `orderingKey` on pub/sub's `Message` type. | ||
|
Original file line number | Diff line number | Diff line change | ||
---|---|---|---|---|
@@ -0,0 +1,68 @@ | ||||
/// This library provides a low-level API for accessing Google's Cloud | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you add the std 3-line copyright header here? For 2025. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: can we call the file |
||||
/// Tasks. | ||||
/// | ||||
/// For more information on Cloud Tasks, please refer to the following | ||||
/// developers page: https://cloud.google.com/tasks/docs | ||||
library; | ||||
|
||||
import 'package:googleapis/cloudtasks/v2.dart' as tasks; | ||||
import 'package:http/http.dart' as http; | ||||
|
||||
import 'service_scope.dart' as ss; | ||||
|
||||
import 'src/cloud_tasks_impl.dart' show CloudTasksImpl; | ||||
|
||||
const Symbol _tasksKey = #gcloud.tasks; | ||||
|
||||
/// Access the [CloudTasks] object available in the current service scope. | ||||
/// | ||||
/// The returned object will be the one which was previously registered with | ||||
/// [registerTasksService] within the current (or a parent) service scope. | ||||
/// | ||||
/// Accessing this getter outside of a service scope will result in an error. | ||||
/// See the `package:gcloud/service_scope.dart` library for more information. | ||||
CloudTasks get tasksService => ss.lookup(_tasksKey) as CloudTasks; | ||||
|
||||
/// Registers the [CloudTasks] object within the current service scope. | ||||
/// | ||||
/// The provided `tasks` object will be available via the top-level | ||||
/// `tasksService` getter. | ||||
/// | ||||
/// Calling this function outside of a service scope will result in an error. | ||||
/// Calling this function more than once inside the same service scope is not | ||||
/// allowed. | ||||
void registerTasksService(CloudTasks tasks) { | ||||
ss.register(_tasksKey, tasks); | ||||
} | ||||
|
||||
/// Interface used to talk to the Google Cloud Tasks service. | ||||
abstract class CloudTasks { | ||||
/// List of required OAuth2 scopes for Cloud Tasks operations. | ||||
// ignore: constant_identifier_names | ||||
static const Scopes = [tasks.CloudTasksApi.cloudPlatformScope]; | ||||
|
||||
/// Access Cloud Tasks using an authenticated client. | ||||
/// | ||||
/// The [client] is an authenticated HTTP client. This client must | ||||
/// provide access to at least the scopes in [CloudTasks.Scopes]. | ||||
factory CloudTasks(http.Client client, String project, String location) { | ||||
return CloudTasksImpl(client, project, location); | ||||
} | ||||
|
||||
/// Creates a new task on the specified [queue]. When the task is run, | ||||
/// [request] will be executed. | ||||
/// | ||||
/// If [scheduleTime] is provided, the task will be scheduled to run at the | ||||
/// specified time. If not provided, the task will be scheduled to run | ||||
/// immediately. | ||||
/// | ||||
/// If [name] is provided, the task will be given that name. | ||||
/// | ||||
/// Returns a [Future] which completes with the newly created task. | ||||
Future<tasks.Task> createTask( | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wonder if we should wrap the Like we do here labs/pkgs/gcloud/lib/src/storage_impl.dart Line 128 in cda0362
|
||||
String queue, | ||||
http.Request request, { | ||||
String? name, | ||||
DateTime? scheduleTime, | ||||
}); | ||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
import 'dart:convert'; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 3-line copyright header |
||
|
||
import 'package:googleapis/cloudtasks/v2.dart' as api; | ||
import 'package:http/http.dart' as http; | ||
|
||
import '../cloud_tasks.dart' as tasks; | ||
|
||
class CloudTasksImpl implements tasks.CloudTasks { | ||
final api.CloudTasksApi _api; | ||
final String _project; | ||
final String _location; | ||
|
||
CloudTasksImpl(http.Client client, String project, String location) | ||
: _api = api.CloudTasksApi(client), | ||
_project = project, | ||
_location = location; | ||
|
||
@override | ||
Future<api.Task> createTask( | ||
String queue, | ||
http.Request request, { | ||
DateTime? scheduleTime, | ||
String? name, | ||
}) async { | ||
final task = api.Task( | ||
name: name, | ||
scheduleTime: scheduleTime?.toUtc().toIso8601String(), | ||
httpRequest: _fromHttpRequest(request), | ||
); | ||
final createTaskRequest = api.CreateTaskRequest(task: task); | ||
return _api.projects.locations.queues.tasks | ||
.create(createTaskRequest, _fullQueueName(queue)); | ||
} | ||
|
||
api.HttpRequest _fromHttpRequest(http.Request request) { | ||
return api.HttpRequest( | ||
headers: request.headers, | ||
body: base64.encode(utf8.encode(request.body)), | ||
httpMethod: request.method, | ||
url: request.url.toString(), | ||
); | ||
} | ||
|
||
String _fullQueueName(String name) { | ||
return 'projects/$_project/locations/$_location/queues/$name'; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
import 'dart:convert'; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. copyright header |
||
|
||
import 'package:gcloud/cloud_tasks.dart'; | ||
import 'package:http/http.dart' as http; | ||
import 'package:test/test.dart'; | ||
|
||
import '../common.dart'; | ||
import '../common_e2e.dart'; | ||
|
||
const _hostName = 'cloudtasks.googleapis.com'; | ||
const _rootPath = '/v2/'; | ||
const _defaultLocation = 'us-central1'; | ||
|
||
MockClient mockClient() => MockClient(_hostName, _rootPath); | ||
|
||
Future<void> withMockClientAsync( | ||
Future Function(MockClient client, CloudTasks tasks) function) async { | ||
var mock = mockClient(); | ||
await function(mock, CloudTasks(mock, testProject, _defaultLocation)); | ||
} | ||
|
||
void main() { | ||
group('task', () { | ||
test('create with httpRequest', () async { | ||
const taskName = 'my-task'; | ||
const requestBody = 'hello world'; | ||
const requestHeaders = { | ||
'content-type': 'application/json', | ||
'authorization': 'Bearer ....' | ||
}; | ||
final expectedTaskJson = { | ||
'name': taskName, | ||
'httpRequest': { | ||
'headers': requestHeaders, | ||
'body': base64.encode(utf8.encode(requestBody)), | ||
'httpMethod': 'GET', | ||
'url': 'https://www.google.com', | ||
}, | ||
}; | ||
final responseJson = {'task': expectedTaskJson}; | ||
|
||
await withMockClientAsync((mock, tasks) async { | ||
mock.register( | ||
'POST', | ||
'projects/test-project/locations/us-central1/queues/test-queue/tasks', | ||
expectAsync1((request) { | ||
final json = jsonDecode(request.body) as Map<String, dynamic>; | ||
expect(json, responseJson); | ||
return mock.respond(expectedTaskJson); | ||
}), | ||
); | ||
|
||
final request = http.Request('GET', Uri.parse('https://www.google.com')) | ||
..body = requestBody | ||
..headers.addAll(requestHeaders); | ||
|
||
final task = | ||
await tasks.createTask('test-queue', request, name: taskName); | ||
expect(task.name, taskName); | ||
final actualRequestJson = task.httpRequest!.toJson(); | ||
expect(actualRequestJson, expectedTaskJson['httpRequest']); | ||
}); | ||
}); | ||
}); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to also update the README.md