/** Handle service periodic maintenance calls. */ @Override public void handleMaintenance(Operation post) { post.complete(); Operation.CompletionHandler handler = (Operation op, Throwable failure) -> { if (null != failure) { // query failed so abort and retry next time logFailure(failure); return; } NodeSelectorService.SelectOwnerResponse rsp = op.getBody(NodeSelectorService.SelectOwnerResponse.class); if (!getHost().getId().equals(rsp.ownerNodeId)) { ServiceUtils.logInfo( TaskTriggerService.this, "Host[%s]: Not owner of scheduler [%s] (Owner Info [%s])", getHost().getId(), getSelfLink(), Utils.toJson(rsp)); return; } State state = new State(); sendSelfPatch(state); }; Operation selectOwnerOp = Operation.createPost(null) .setExpiration(ServiceUtils.computeExpirationTime(OWNER_SELECTION_TIMEOUT_MILLIS)) .setCompletion(handler); getHost().selectOwner(null, getSelfLink(), selectOwnerOp); }
@Test(dataProvider = "ValidStartStages") public void testValidStartState(TaskState.TaskStage startStage) throws Throwable { CreateContainerSpecTaskService.State startState = buildValidStartState(startStage); Operation startOperation = testHost.startServiceSynchronously(createContainerSpecTaskService, startState); assertThat(startOperation.getStatusCode(), is(200)); }
@Override public void handleStart(Operation startOperation) { ServiceUtils.logInfo(this, "Starting service %s", getSelfLink()); State startState = startOperation.getBody(State.class); InitializationUtils.initialize(startState); if (null == startState.taskPollDelay) { startState.taskPollDelay = HostUtils.getDeployerContext(this).getTaskPollDelay(); } validateState(startState); if (TaskState.TaskStage.CREATED == startState.taskState.stage) { startState.taskState.stage = TaskState.TaskStage.STARTED; } startOperation.setBody(startState).complete(); try { if (ControlFlags.isOperationProcessingDisabled(startState.controlFlags)) { ServiceUtils.logInfo(this, "Skipping start operation processing (disabled)"); } else if (TaskState.TaskStage.STARTED == startState.taskState.stage) { sendStageProgressPatch(startState.taskState.stage); } } catch (Throwable t) { failTask(t); } }
@Override public void handleStart(Operation startOperation) { ServiceUtils.logInfo(this, "Starting service %s", getSelfLink()); State startState = startOperation.getBody(State.class); InitializationUtils.initialize(startState); ValidationUtils.validateState(startState); startOperation.complete(); }
@Override public void handleStart(Operation start) { try { validateState(start); start.complete(); } catch (Exception e) { start.fail(e); } }
@Override public void handlePatch(Operation patchOperation) { ServiceUtils.logInfo(this, "Handling patch for service %s", getSelfLink()); State currentState = getState(patchOperation); State patchState = patchOperation.getBody(State.class); ValidationUtils.validatePatch(currentState, patchState); PatchUtils.patchState(currentState, patchState); ValidationUtils.validateState(currentState); patchOperation.complete(); }
private void validateState(Operation start) { if (!start.hasBody()) { throw new IllegalArgumentException("attempt to initialize service with an empty state"); } BankAccountServiceState state = start.getBody(BankAccountServiceState.class); if (state.balance < 0) { throw new IllegalArgumentException("balance cannot be negative"); } }
void handlePatchForDeposit(Operation patch) { BankAccountServiceState currentState = getState(patch); BankAccountServiceRequest body = patch.getBody(BankAccountServiceRequest.class); currentState.balance += body.amount; setState(patch, currentState); patch.setBody(currentState); patch.complete(); }
@Test public void testMinimalStartState() throws Throwable { CreateContainerSpecTaskService.State startState = buildValidStartState(); Operation startOperation = testHost.startServiceSynchronously(createContainerSpecTaskService, startState); assertThat(startOperation.getStatusCode(), is(200)); CreateContainerSpecTaskService.State savedState = testHost.getServiceState(CreateContainerSpecTaskService.State.class); assertThat(savedState.taskState.stage, is(TaskState.TaskStage.STARTED)); }
@Override public void handlePatch(Operation patch) { State currentState = getState(patch); State patchState = patch.getBody(State.class); this.validatePatch(currentState, patchState); this.applyPatch(currentState, patchState); this.validateState(currentState); patch.complete(); this.processPatch(currentState); }
@Test(dataProvider = "StartStagesWhichTransitionToStarted") public void testStartStateTransitionsToStarted(TaskState.TaskStage startStage) throws Throwable { CreateContainerSpecTaskService.State startState = buildValidStartState(startStage); Operation startOperation = testHost.startServiceSynchronously(createContainerSpecTaskService, startState); assertThat(startOperation.getStatusCode(), is(200)); CreateContainerSpecTaskService.State savedState = testHost.getServiceState(CreateContainerSpecTaskService.State.class); assertThat(savedState.taskState.stage, is(TaskState.TaskStage.STARTED)); }
@Test(dataProvider = "FinalStartStages") public void testFinalStartState(TaskState.TaskStage startStage) throws Throwable { CreateContainerSpecTaskService.State startState = buildValidStartState(startStage); startState.controlFlags = 0; Operation startOperation = testHost.startServiceSynchronously(createContainerSpecTaskService, startState); assertThat(startOperation.getStatusCode(), is(200)); CreateContainerSpecTaskService.State savedState = testHost.getServiceState(CreateContainerSpecTaskService.State.class); assertThat(savedState.taskState.stage, is(startStage)); }
@Override public void handleStart(Operation start) { ServiceUtils.logInfo(this, "Starting service %s", getSelfLink()); State s = start.getBody(State.class); this.initializeState(s); this.validateState(s); // set the maintenance interval to match the value in the state. this.setMaintenanceIntervalMicros(TimeUnit.MILLISECONDS.toMicros(s.triggerIntervalMillis)); start.complete(); }
@Test public void testGetServiceStateWithDefaultPath() throws Throwable { ExampleService exampleService = new ExampleService(); ExampleService.ExampleServiceState exampleServiceState = new ExampleService.ExampleServiceState(); exampleServiceState.name = UUID.randomUUID().toString(); Operation post = host.startServiceSynchronously(exampleService, exampleServiceState); assertThat(post.getStatusCode(), is(200)); ExampleService.ExampleServiceState result = host.getServiceState(ExampleService.ExampleServiceState.class); assertThat(result.name, is(exampleServiceState.name)); }
void handlePatchForWithdraw(Operation patch) { BankAccountServiceState currentState = getState(patch); BankAccountServiceRequest body = patch.getBody(BankAccountServiceRequest.class); if (body.amount > currentState.balance) { patch.fail(new IllegalArgumentException("Not enough funds to withdraw")); return; } currentState.balance -= body.amount; setState(patch, currentState); patch.setBody(currentState); patch.complete(); }
private void createTenantEntity(final String tenantId) { final Service service = this; Operation.CompletionHandler completionHandler = new Operation.CompletionHandler() { @Override public void handle(Operation operation, Throwable throwable) { if (null != throwable) { failTask(throwable); } try { State patchState = buildPatch(TaskState.TaskStage.FINISHED, null); patchState.tenantServiceLink = operation.getBody(TenantService.State.class).documentSelfLink; TaskUtils.sendSelfPatch(service, patchState); } catch (Throwable t) { failTask(t); } } }; Operation op = Operation.createPost(UriUtils.buildUri(getHost(), TenantFactoryService.SELF_LINK)) .setBody(createTenantServiceState(tenantId)) .setCompletion(completionHandler); sendRequest(op); }
@Override public void handleGet(Operation get) { try { FileUtils.readFileAndComplete(get, this.file); } catch (IOException e) { get.fail(e); } }
@Test(dataProvider = "ValidStageTransitions") public void testValidStageTransition( TaskState.TaskStage startStage, TaskState.TaskStage patchStage) throws Throwable { startService(startStage); CreateContainerSpecTaskService.State patchState = createContainerSpecTaskService.buildPatch(patchStage, null); Operation patchOperation = Operation.createPatch(UriUtils.buildUri(testHost, TestHost.SERVICE_URI, null)) .setBody(patchState); Operation result = testHost.sendRequestAndWait(patchOperation); assertThat(result.getStatusCode(), is(200)); CreateContainerSpecTaskService.State savedState = testHost.getServiceState(CreateContainerSpecTaskService.State.class); assertThat(savedState.taskState.stage, is(patchStage)); }
@Override public void handlePatch(Operation patchOperation) { ServiceUtils.logInfo(this, "Handling patch for service %s", getSelfLink()); State startState = getState(patchOperation); State patchState = patchOperation.getBody(State.class); validatePatchState(startState, patchState); State currentState = applyPatch(startState, patchState); validateState(currentState); patchOperation.complete(); try { if (ControlFlags.isOperationProcessingDisabled(currentState.controlFlags)) { ServiceUtils.logInfo(this, "Skipping patch operation processing (disabled)"); } else if (TaskState.TaskStage.STARTED == currentState.taskState.stage) { createTenant(currentState); } } catch (Throwable t) { failTask(t); } }
/** * Trigger image replication. * * @param request * @return * @throws Throwable */ private String triggerReplication(ReplicateImageRequest request) throws Throwable { // Prepare replication service call. ImageReplicatorService.State postReq = new ImageReplicatorService.State(); postReq.image = request.getImage(); postReq.datastore = request.getDatastore(); // Create the operation and call for replication. Operation postOperation = Operation.createPost(UriUtils.buildUri(dcpHost, ImageReplicatorServiceFactory.class)) .setBody(postReq) .setReferer(UriUtils.buildUri(dcpHost, REFERRER_PATH)) .setExpiration(Utils.getNowMicrosUtc() + dcpOperationTimeoutMicros) .setContextId(LoggingUtils.getRequestId()); OperationLatch opLatch = new OperationLatch(postOperation); dcpHost.sendRequest(postOperation); Operation op = opLatch.await(); // Return operation id. return op.getBody(ImageReplicatorService.State.class).documentSelfLink; }
/** * Get service state by serviceLink. * * @param path * @return * @throws Throwable */ private ImageReplicatorService.State getLatestState(String path) throws Throwable { Operation getOperation = Operation.createGet(UriUtils.buildUri(dcpHost, path)) .setReferer(UriUtils.buildUri(dcpHost, REFERRER_PATH)) .setExpiration(Utils.getNowMicrosUtc() + dcpOperationTimeoutMicros) .setContextId(LoggingUtils.getRequestId()); OperationLatch opLatch = new OperationLatch(getOperation); dcpHost.sendRequest(getOperation); return opLatch.await().getBody(ImageReplicatorService.State.class); }
public DcpException( Operation requestedOperation, OperationLatch.OperationResult operationResult) { super( operationResult.completedOperation == null ? requestedOperation.toString() : operationResult.completedOperation.toString(), operationResult.operationFailure); this.requestedOperation = requestedOperation; this.operationResult = operationResult; }
@Test public void testWaitForState() throws Throwable { ExampleService exampleService = new ExampleService(); final ExampleService.ExampleServiceState exampleServiceState = new ExampleService.ExampleServiceState(); exampleServiceState.name = UUID.randomUUID().toString(); Operation post = host.startServiceSynchronously(exampleService, exampleServiceState); assertThat(post.getStatusCode(), is(200)); try { host.waitForState( ExampleService.ExampleServiceState.class, new Predicate<ExampleService.ExampleServiceState>() { @Override public boolean test(ExampleService.ExampleServiceState state) { return false; } }); Assert.fail("this state transition should not have succeeded"); } catch (TimeoutException e) { assertThat( e.getMessage(), is(equalToIgnoringCase("timeout waiting for state transition."))); } try { host.waitForState( ExampleService.ExampleServiceState.class, new Predicate<ExampleService.ExampleServiceState>() { @Override public boolean test(ExampleService.ExampleServiceState state) { return state.name.equals(exampleServiceState.name); } }); } catch (RuntimeException runtimeException) { Assert.fail("failed to detect state transition"); } }
/** * Does any additional processing after the patch operation has been completed. * * @param current */ private void processPatch(final State current) { try { Type stateType = Class.forName(current.triggerStateClassName); ServiceDocument postState = Utils.fromJson(current.serializedTriggerState, stateType); postState.documentExpirationTimeMicros = ServiceUtils.computeExpirationTime(current.taskExpirationAgeMillis); Operation post = Operation.createPost(UriUtils.buildUri(getHost(), current.factoryServiceLink)) .setBody(postState); this.sendRequest(post); } catch (ClassNotFoundException ex) { logFailure(ex); } }
@Test( dataProvider = "InvalidStageTransitions", expectedExceptions = IllegalStateException.class) public void testInvalidStageTransition( TaskState.TaskStage startStage, TaskState.TaskStage patchStage) throws Throwable { startService(startStage); CreateContainerSpecTaskService.State patchState = createContainerSpecTaskService.buildPatch(patchStage, null); Operation patchOperation = Operation.createPatch(UriUtils.buildUri(testHost, TestHost.SERVICE_URI, null)) .setBody(patchState); testHost.sendRequestAndWait(patchOperation); }
@Test( dataProvider = "InvalidPatchStateAttributes", expectedExceptions = IllegalStateException.class) public void testInvalidPatchStateInvalidAttributeSet(String attributeName, Object value) throws Throwable { startService(TaskState.TaskStage.CREATED); CreateContainerSpecTaskService.State patchState = createContainerSpecTaskService.buildPatch(TaskState.TaskStage.STARTED, null); patchState.getClass().getDeclaredField(attributeName).set(patchState, value); Operation patchOperation = Operation.createPatch(UriUtils.buildUri(testHost, TestHost.SERVICE_URI, null)) .setBody(patchState); testHost.sendRequestAndWait(patchOperation); }
private void startService(TaskState.TaskStage startStage) throws Throwable { CreateContainerSpecTaskService.State startState = buildValidStartState(startStage); Operation startOperation = testHost.startServiceSynchronously(createContainerSpecTaskService, startState); assertThat(startOperation.getStatusCode(), is(200)); }
public DcpException(Operation operation) { super(operation.toString()); this.requestedOperation = operation; }
@Test public void testWaitForQuery() throws Throwable { ExampleService exampleService = new ExampleService(); final ExampleService.ExampleServiceState exampleServiceState = new ExampleService.ExampleServiceState(); exampleServiceState.name = UUID.randomUUID().toString(); QueryTask.Query kindClause = new QueryTask.Query() .setTermPropertyName(ServiceDocument.FIELD_NAME_KIND) .setTermMatchValue(Utils.buildKind(ExampleService.ExampleServiceState.class)); QueryTask.Query nameClause = new QueryTask.Query() .setTermPropertyName("name") .setTermMatchValue(exampleServiceState.name); QueryTask.QuerySpecification spec = new QueryTask.QuerySpecification(); spec.query.addBooleanClause(kindClause); spec.query.addBooleanClause(nameClause); spec.options = EnumSet.of(QueryTask.QuerySpecification.QueryOption.EXPAND_CONTENT); QueryTask query = QueryTask.create(spec).setDirect(true); try { host.waitForQuery( query, new Predicate<QueryTask>() { @Override public boolean test(QueryTask queryTask) { return queryTask.results.documentLinks.size() > 0; } }); Assert.fail("waitForQuery should not have succeeded before documents are created"); } catch (RuntimeException runtimeException) { assertThat( runtimeException.getMessage(), is(equalToIgnoringCase("timeout waiting for query result."))); } Operation post = host.startServiceSynchronously(exampleService, exampleServiceState); assertThat(post.getStatusCode(), is(200)); ExampleService.ExampleServiceState result = host.getServiceState(ExampleService.ExampleServiceState.class); assertThat(result.name, is(exampleServiceState.name)); QueryTask response = host.waitForQuery( query, new Predicate<QueryTask>() { @Override public boolean test(QueryTask queryTask) { return queryTask.results.documentLinks.size() > 0; } }); assertThat(response.results.documentLinks.size(), is(1)); // verify fields are passed down correctly for (Map.Entry<String, Object> document : response.results.documents.entrySet()) { ExampleService.ExampleServiceState docState = Utils.fromJson(document.getValue(), ExampleService.ExampleServiceState.class); assertThat(docState.name, is(equalTo(exampleServiceState.name))); } }
@Override public void handleStart(Operation startPost) { startPost.fail(new Exception(ERROR_MESSAGE)); }