use of com.google.appengine.api.taskqueue.TaskQueuePb.TaskQueueAddRequest in project appengine-java-standard by GoogleCloudPlatform.
the class QueueImpl method addAsync.
/**
* See {@link Queue#addAsync(com.google.appengine.api.datastore.Transaction, Iterable)}.
*/
@Override
public Future<List<TaskHandle>> addAsync(Transaction txn, Iterable<TaskOptions> taskOptions) {
final List<TaskOptions> taskOptionsList = new ArrayList<>();
Set<String> taskNames = new HashSet<>();
final TaskQueueBulkAddRequest.Builder bulkAddRequest = TaskQueueBulkAddRequest.newBuilder();
boolean hasPushTask = false;
boolean hasPullTask = false;
for (TaskOptions option : taskOptions) {
TaskQueueAddRequest.Builder addRequest = bulkAddRequest.addAddRequestBuilder();
validateAndFillAddRequest(txn, option, addRequest);
if (addRequest.getMode() == TaskQueueMode.Mode.PULL) {
hasPullTask = true;
} else {
hasPushTask = true;
}
taskOptionsList.add(option);
if (option.getTaskName() != null && !option.getTaskName().isEmpty()) {
if (!taskNames.add(option.getTaskName())) {
throw new IllegalArgumentException(String.format("Identical task names in request : \"%s\" duplicated", option.getTaskName()));
}
}
}
if (bulkAddRequest.getAddRequestCount() > QueueConstants.maxTasksPerAdd()) {
throw new IllegalArgumentException(String.format("No more than %d tasks can be added in a single add call", QueueConstants.maxTasksPerAdd()));
}
if (hasPullTask && hasPushTask) {
throw new IllegalArgumentException("May not add both push tasks and pull tasks in the same call.");
}
TaskQueueBulkAddRequest builtRequest = bulkAddRequest.build();
if (txn != null && builtRequest.getSerializedSize() > QueueConstants.maxTransactionalRequestSizeBytes()) {
throw new IllegalArgumentException(String.format("Transactional add may not be larger than %d bytes: %d bytes requested.", QueueConstants.maxTransactionalRequestSizeBytes(), builtRequest.getSerializedSize()));
}
Future<TaskQueueBulkAddResponse> responseFuture = makeAsyncCall("BulkAdd", builtRequest, TaskQueueBulkAddResponse.getDefaultInstance());
return new FutureAdapter<TaskQueueBulkAddResponse, List<TaskHandle>>(responseFuture) {
@Override
protected List<TaskHandle> wrap(TaskQueueBulkAddResponse bulkAddResponse) {
if (bulkAddResponse.getTaskResultCount() != bulkAddRequest.getAddRequestCount()) {
throw new InternalFailureException(String.format("expected %d results from BulkAdd(), got %d", bulkAddRequest.getAddRequestCount(), bulkAddResponse.getTaskResultCount()));
}
List<TaskHandle> tasks = new ArrayList<>();
RuntimeException taskqueueException = null;
for (int i = 0; i < bulkAddResponse.getTaskResultCount(); ++i) {
TaskQueueBulkAddResponse.TaskResult.Builder taskResult = bulkAddResponse.toBuilder().getTaskResultBuilder(i);
TaskQueueAddRequest addRequest = bulkAddRequest.getAddRequest(i);
TaskOptions options = taskOptionsList.get(i);
if (taskResult.getResult() == TaskQueueServiceError.ErrorCode.OK) {
String taskName = options.getTaskName();
if (taskResult.hasChosenTaskName()) {
taskName = taskResult.getChosenTaskName().toStringUtf8();
}
TaskOptions taskResultOptions = new TaskOptions(options);
taskResultOptions.taskName(taskName).payload(addRequest.getBody().toByteArray());
TaskHandle handle = new TaskHandle(taskResultOptions, queueName);
tasks.add(handle.etaUsec(addRequest.getEtaUsec()));
} else if (taskResult.getResult() != TaskQueueServiceError.ErrorCode.SKIPPED) {
// not successfully added.
if (taskqueueException == null || taskqueueException instanceof TaskAlreadyExistsException) {
int result = taskResult.getResult().getNumber();
String detail = (result == TaskQueueServiceError.ErrorCode.UNKNOWN_QUEUE_VALUE) ? queueName : options.getTaskName();
RuntimeException e = QueueApiHelper.translateError(result, detail);
if (e instanceof TaskAlreadyExistsException) {
if (taskqueueException == null) {
taskqueueException = e;
}
TaskAlreadyExistsException taee = (TaskAlreadyExistsException) taskqueueException;
taee.appendTaskName(options.getTaskName());
} else {
taskqueueException = e;
}
}
}
}
if (taskqueueException != null) {
throw taskqueueException;
}
return tasks;
}
};
}
use of com.google.appengine.api.taskqueue.TaskQueuePb.TaskQueueAddRequest in project appengine-java-standard by GoogleCloudPlatform.
the class LocalDatastoreService method addActionsImpl.
// status
@SuppressWarnings("unused")
private void addActionsImpl(Status status, TaskQueueBulkAddRequest request) {
if (request.getAddRequestCount() == 0) {
return;
}
// The transactional tasks need to be associated with the txn.
// When the txn is committed the tasks will be sent back over to
// the taskqueue stub. We need to wipe out their transactions before sending
// so that the tasks actually get added and we don't continue spinning
// around in and infinite loop.
List<TaskQueueAddRequest> addRequests = new ArrayList<>(request.getAddRequestCount());
for (TaskQueueAddRequest addRequest : request.getAddRequestList()) {
addRequests.add(addRequest.toBuilder().clearTransaction().clearDatastoreTransaction().build());
}
Transaction transaction;
if (request.getAddRequestList().get(0).hasDatastoreTransaction()) {
ByteString datastoreTransaction = request.getAddRequestList().get(0).getDatastoreTransaction();
try {
transaction = Transaction.parser().parseFrom(datastoreTransaction);
} catch (InvalidProtocolBufferException e) {
throw newError(ErrorCode.BAD_REQUEST, "Invalid transaction");
}
} else {
transaction = toProto1(request.getAddRequest(0).getTransaction());
}
Profile profile = profiles.get(transaction.getApp());
LiveTxn liveTxn = profile.getTxn(transaction.getHandle());
liveTxn.addActions(addRequests);
}
use of com.google.appengine.api.taskqueue.TaskQueuePb.TaskQueueAddRequest in project appengine-java-standard by GoogleCloudPlatform.
the class LocalDatastoreService method commit.
// status
@SuppressWarnings("unused")
public CommitResponse commit(Status status, final Transaction req) {
Profile profile = profiles.get(req.getApp());
checkNotNull(profile);
CommitResponse response = new CommitResponse();
globalLock.readLock().lock();
// Synchronized so we can't commit and rollback at the same time.
synchronized (profile) {
LiveTxn liveTxn;
try {
liveTxn = profile.removeTxn(req.getHandle());
try {
if (liveTxn.isDirty()) {
response = commitImpl(liveTxn, profile);
} else {
// cost of a read-only txn is 0
response.setCost(new Cost().setEntityWrites(0).setIndexWrites(0));
}
} catch (ApplicationException e) {
// commit failed, re-add transaction so that it can be rolled back or reset.
profile.addTxn(req.getHandle(), new LiveTxn(clock, liveTxn.allowMultipleEg, liveTxn.originalTransactionMode, true));
throw e;
}
} finally {
globalLock.readLock().unlock();
}
// taskqueue tasks become durable.
for (TaskQueueAddRequest action : liveTxn.getActions()) {
try {
addActionImpl(action);
} catch (ApplicationException e) {
logger.log(Level.WARNING, "Transactional task: " + action + " has been dropped.", e);
}
}
}
return response;
}
use of com.google.appengine.api.taskqueue.TaskQueuePb.TaskQueueAddRequest in project appengine-java-standard by GoogleCloudPlatform.
the class LocalTaskQueue method queryAndOwnTasks.
@LatencyPercentiles(latency50th = 8)
public TaskQueueQueryAndOwnTasksResponse queryAndOwnTasks(Status status, TaskQueueQueryAndOwnTasksRequest request) {
String queueName = request.getQueueName().toStringUtf8();
validateQueueName(queueName);
// getQueueByName will throw UNKNOWN_QUEUE if the queue does not exist.
DevQueue queue = getQueueByName(queueName);
if (queue.getMode() != Mode.PULL) {
throw new ApiProxy.ApplicationException(ErrorCode.INVALID_QUEUE_MODE_VALUE);
}
DevPullQueue pullQueue = (DevPullQueue) queue;
List<TaskQueueAddRequest.Builder> results = pullQueue.queryAndOwnTasks(request.getLeaseSeconds(), request.getMaxTasks(), request.hasGroupByTag(), request.getTag().toByteArray());
TaskQueueQueryAndOwnTasksResponse.Builder response = TaskQueueQueryAndOwnTasksResponse.newBuilder();
for (TaskQueueAddRequest.Builder task : results) {
TaskQueueQueryAndOwnTasksResponse.Task.Builder responseTask = response.addTaskBuilder().setTaskName(task.getTaskName()).setBody(task.getBody()).setEtaUsec(task.getEtaUsec());
if (task.hasTag()) {
responseTask.setTag(task.getTag());
}
// TODO: To keep track of retry count, we can replace TaskQueueAddRequest with
// TaskQueueQueryTasksResponse to represent a task.
}
return response.build();
}
Aggregations