blob: b16ccdf9e843763425fd3fbf0f25c2d0d6f98dd1 [file] [log] [blame]
// Copyright 2020 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:cocoon_service/src/model/appengine/task.dart';
import 'package:cocoon_service/src/service/datastore.dart';
/// Function signature for a [ReservationService] provider.
typedef ReservationServiceProvider = ReservationService Function(
DatastoreService datastoreService);
class ReservationService {
const ReservationService(this.datastore);
final DatastoreService datastore;
/// Creates and returns a [ReservationService] using [datastore].
static ReservationService defaultProvider(DatastoreService datastore) {
return ReservationService(datastore);
}
/// If another agent has obtained the reservation on the task before we've
/// been able to secure our reservation, ths will throw a
/// [ReservationLostException]
Future<void> secureReservation(Task task, String agentId) async {
assert(task != null);
assert(agentId != null);
try {
final Task lockedTask = await datastore.lookupByValue<Task>(task.key);
if (lockedTask.status != Task.statusNew) {
// Another reservation beat us in a race.
throw const ReservationLostException();
}
lockedTask.status = Task.statusInProgress;
lockedTask.attempts += 1;
lockedTask.startTimestamp = DateTime.now().millisecondsSinceEpoch;
lockedTask.reservedForAgentId = agentId;
await datastore.insert(<Task>[lockedTask]);
} catch (error) {
throw const ReservationLostException();
}
}
}
/// Exception representing an attempt to secure a task reservation that was
/// preempted by another reservation holder.
class ReservationLostException implements Exception {
/// Creates a new [ReservationLostException].
const ReservationLostException();
}