@Test public void testConsume() { Job<BatchJobExt> job = newBatchJob(10, budget(percentageOfHealthyPolicy(80.0), hourlyRatePercentage(20), Collections.emptyList())); com.netflix.titus.api.model.reference.Reference jobReference = com.netflix.titus.api.model.reference.Reference.job(job.getId()); scheduleJob(job, 10); JobQuotaController jobController = new JobQuotaController(job, jobOperations, SelfJobDisruptionBudgetResolver.getInstance(), containerHealthService, titusRuntime); assertThat(jobController.getQuota(jobReference).getQuota()).isEqualTo(2); Task task = jobOperations.getTasks(job.getId()).get(0); assertThat(jobController.consume(task.getId()).isApproved()).isTrue(); assertThat(jobController.consume(task.getId()).isApproved()).isTrue(); assertThat(jobController.getQuota(jobReference).getQuota()).isEqualTo(0); ConsumptionResult failure = jobController.consume(task.getId()); assertThat(failure.isApproved()).isFalse(); assertThat(failure.getRejectionReason().get()).contains("JobPercentagePerHourRelocationRateController"); }
@Override public ConsumptionResult consume(String taskId) { if (isLegacy()) { return LEGACY; } Reference taskReference = Reference.task(taskId); StringBuilder rejectionResponseBuilder = new StringBuilder("MissingQuotas["); boolean noQuota = false; for (QuotaTracker tracker : quotaTrackers) { EvictionQuota quotaStatus = tracker.getQuota(taskReference); if (quotaStatus.getQuota() <= 0) { noQuota = true; rejectionResponseBuilder.append(tracker.getClass().getSimpleName()).append('=').append(quotaStatus.getMessage()).append(", "); } } if (noQuota) { rejectionResponseBuilder.setLength(rejectionResponseBuilder.length() - 2); return ConsumptionResult.rejected(rejectionResponseBuilder.append(']').toString()); } for (int i = 0; i < quotaControllers.size(); i++) { QuotaController<Job<?>> controller = quotaControllers.get(i); ConsumptionResult result = controller.consume(taskId); if (!result.isApproved()) { for (int j = 0; j < i; j++) { quotaControllers.get(j).giveBackConsumedQuota(taskId); } rejectionResponseBuilder .append(controller.getClass().getSimpleName()) .append('=') .append(result.getRejectionReason().orElse("no quota")); return ConsumptionResult.rejected(rejectionResponseBuilder.append(']').toString()); } } return ConsumptionResult.approved(); }
JobQuotaController implements QuotaController<Job<?>> { @Override public ConsumptionResult consume(String taskId) { if (isLegacy()) { return LEGACY; } Reference taskReference = Reference.task(taskId); StringBuilder rejectionResponseBuilder = new StringBuilder("MissingQuotas["); boolean noQuota = false; for (QuotaTracker tracker : quotaTrackers) { EvictionQuota quotaStatus = tracker.getQuota(taskReference); if (quotaStatus.getQuota() <= 0) { noQuota = true; rejectionResponseBuilder.append(tracker.getClass().getSimpleName()).append('=').append(quotaStatus.getMessage()).append(", "); } } if (noQuota) { rejectionResponseBuilder.setLength(rejectionResponseBuilder.length() - 2); return ConsumptionResult.rejected(rejectionResponseBuilder.append(']').toString()); } for (int i = 0; i < quotaControllers.size(); i++) { QuotaController<Job<?>> controller = quotaControllers.get(i); ConsumptionResult result = controller.consume(taskId); if (!result.isApproved()) { for (int j = 0; j < i; j++) { quotaControllers.get(j).giveBackConsumedQuota(taskId); } rejectionResponseBuilder .append(controller.getClass().getSimpleName()) .append('=') .append(result.getRejectionReason().orElse("no quota")); return ConsumptionResult.rejected(rejectionResponseBuilder.append(']').toString()); } } return ConsumptionResult.approved(); } }
JobQuotaController implements QuotaController<Job<?>> { @Override public ConsumptionResult consume(String taskId) { if (isLegacy()) { return LEGACY; } Reference taskReference = Reference.task(taskId); StringBuilder rejectionResponseBuilder = new StringBuilder("MissingQuotas["); boolean noQuota = false; for (QuotaTracker tracker : quotaTrackers) { EvictionQuota quotaStatus = tracker.getQuota(taskReference); if (quotaStatus.getQuota() <= 0) { noQuota = true; rejectionResponseBuilder.append(tracker.getClass().getSimpleName()).append('=').append(quotaStatus.getMessage()).append(", "); } } if (noQuota) { rejectionResponseBuilder.setLength(rejectionResponseBuilder.length() - 2); return ConsumptionResult.rejected(rejectionResponseBuilder.append(']').toString()); } for (int i = 0; i < quotaControllers.size(); i++) { QuotaController<Job<?>> controller = quotaControllers.get(i); ConsumptionResult result = controller.consume(taskId); if (!result.isApproved()) { for (int j = 0; j < i; j++) { quotaControllers.get(j).giveBackConsumedQuota(taskId); } rejectionResponseBuilder .append(controller.getClass().getSimpleName()) .append('=') .append(result.getRejectionReason().orElse("no quota")); return ConsumptionResult.rejected(rejectionResponseBuilder.append(']').toString()); } } return ConsumptionResult.approved(); } JobQuotaController(Job<?> job,
                              V3JobOperations jobOperations,
                              EffectiveJobDisruptionBudgetResolver effectiveDisruptionBudgetResolver,
                              ContainerHealthService containerHealthService,
                              TitusRuntime titusRuntime); private  JobQuotaController(Job<?> newJob,
                               V3JobOperations jobOperations,
                               EffectiveJobDisruptionBudgetResolver effectiveDisruptionBudgetResolver,
                               ContainerHealthService containerHealthService,
                               JobQuotaController previousJobQuotaController,
                               TitusRuntime titusRuntime); }
JobQuotaController implements QuotaController<Job<?>> { @Override public ConsumptionResult consume(String taskId) { if (isLegacy()) { return LEGACY; } Reference taskReference = Reference.task(taskId); StringBuilder rejectionResponseBuilder = new StringBuilder("MissingQuotas["); boolean noQuota = false; for (QuotaTracker tracker : quotaTrackers) { EvictionQuota quotaStatus = tracker.getQuota(taskReference); if (quotaStatus.getQuota() <= 0) { noQuota = true; rejectionResponseBuilder.append(tracker.getClass().getSimpleName()).append('=').append(quotaStatus.getMessage()).append(", "); } } if (noQuota) { rejectionResponseBuilder.setLength(rejectionResponseBuilder.length() - 2); return ConsumptionResult.rejected(rejectionResponseBuilder.append(']').toString()); } for (int i = 0; i < quotaControllers.size(); i++) { QuotaController<Job<?>> controller = quotaControllers.get(i); ConsumptionResult result = controller.consume(taskId); if (!result.isApproved()) { for (int j = 0; j < i; j++) { quotaControllers.get(j).giveBackConsumedQuota(taskId); } rejectionResponseBuilder .append(controller.getClass().getSimpleName()) .append('=') .append(result.getRejectionReason().orElse("no quota")); return ConsumptionResult.rejected(rejectionResponseBuilder.append(']').toString()); } } return ConsumptionResult.approved(); } JobQuotaController(Job<?> job,
                              V3JobOperations jobOperations,
                              EffectiveJobDisruptionBudgetResolver effectiveDisruptionBudgetResolver,
                              ContainerHealthService containerHealthService,
                              TitusRuntime titusRuntime); private  JobQuotaController(Job<?> newJob,
                               V3JobOperations jobOperations,
                               EffectiveJobDisruptionBudgetResolver effectiveDisruptionBudgetResolver,
                               ContainerHealthService containerHealthService,
                               JobQuotaController previousJobQuotaController,
                               TitusRuntime titusRuntime); Job<?> getJob(); @Override EvictionQuota getQuota(Reference reference); @Override ConsumptionResult consume(String taskId); @Override void giveBackConsumedQuota(String taskId); @Override JobQuotaController update(Job<?> updatedJob); }
JobQuotaController implements QuotaController<Job<?>> { @Override public ConsumptionResult consume(String taskId) { if (isLegacy()) { return LEGACY; } Reference taskReference = Reference.task(taskId); StringBuilder rejectionResponseBuilder = new StringBuilder("MissingQuotas["); boolean noQuota = false; for (QuotaTracker tracker : quotaTrackers) { EvictionQuota quotaStatus = tracker.getQuota(taskReference); if (quotaStatus.getQuota() <= 0) { noQuota = true; rejectionResponseBuilder.append(tracker.getClass().getSimpleName()).append('=').append(quotaStatus.getMessage()).append(", "); } } if (noQuota) { rejectionResponseBuilder.setLength(rejectionResponseBuilder.length() - 2); return ConsumptionResult.rejected(rejectionResponseBuilder.append(']').toString()); } for (int i = 0; i < quotaControllers.size(); i++) { QuotaController<Job<?>> controller = quotaControllers.get(i); ConsumptionResult result = controller.consume(taskId); if (!result.isApproved()) { for (int j = 0; j < i; j++) { quotaControllers.get(j).giveBackConsumedQuota(taskId); } rejectionResponseBuilder .append(controller.getClass().getSimpleName()) .append('=') .append(result.getRejectionReason().orElse("no quota")); return ConsumptionResult.rejected(rejectionResponseBuilder.append(']').toString()); } } return ConsumptionResult.approved(); } JobQuotaController(Job<?> job,
                              V3JobOperations jobOperations,
                              EffectiveJobDisruptionBudgetResolver effectiveDisruptionBudgetResolver,
                              ContainerHealthService containerHealthService,
                              TitusRuntime titusRuntime); private  JobQuotaController(Job<?> newJob,
                               V3JobOperations jobOperations,
                               EffectiveJobDisruptionBudgetResolver effectiveDisruptionBudgetResolver,
                               ContainerHealthService containerHealthService,
                               JobQuotaController previousJobQuotaController,
                               TitusRuntime titusRuntime); Job<?> getJob(); @Override EvictionQuota getQuota(Reference reference); @Override ConsumptionResult consume(String taskId); @Override void giveBackConsumedQuota(String taskId); @Override JobQuotaController update(Job<?> updatedJob);  }