@Override
  protected void runOneIteration() {
    monitor.debug(() -> "JobMetadata.isInitialized(): " + JobMetadata.isInitialized());
    if (JobMetadata.isInitialized()) {
      if (stopwatch.elapsed(TimeUnit.SECONDS) > credsTimeoutSeconds) {
        UUID jobId = JobMetadata.getJobId();
        markJobTimedOut(jobId);
        String message =
            format(
                "Waited over %d seconds for the creds to be provided on the claimed job: %s",
                credsTimeoutSeconds, jobId);
        monitor.severe(() -> message, EventCode.WORKER_CREDS_TIMEOUT);
        throw new CredsTimeoutException(message, jobId);
      }
      pollUntilJobIsReady();
    } else {
      // Poll for an unassigned job to process with this transfer worker instance.
      // Once a transfer worker instance is assigned, the client will populate storage with
      // auth data encrypted with this instances public key and the copy process can begin
      pollForUnassignedJob();
    }
  }
@Test
  public void pollingLifeCycle() throws Exception {

    when(asymmetricKeyGenerator.generate()).thenReturn(TEST_KEY_PAIR);
    // Initial state
    assertThat(JobMetadata.isInitialized()).isFalse();

    // Run once with no data in the database
    jobPollingService.runOneIteration();
    assertThat(JobMetadata.isInitialized()).isFalse();
    PortabilityJob job = store.findJob(TEST_ID);
    assertThat(job).isNull(); // No existing ready job

    // API inserts an job in initial authorization state
    job =
        PortabilityJob.builder()
            .setTransferDataType(DataVertical.PHOTOS)
            .setExportService("DummyExportService")
            .setImportService("DummyImportService")
            .setAndValidateJobAuthorization(
                JobAuthorization.builder()
                    .setEncryptionScheme("cleartext")
                    .setState(State.INITIAL)
                    .setSessionSecretKey("fooBar")
                    .build())
            .build();
    store.createJob(TEST_ID, job);

    // Verify initial authorization state
    job = store.findJob(TEST_ID);
    assertThat(job.jobAuthorization().state()).isEqualTo(State.INITIAL);
    // no auth data should exist yet
    assertThat(job.jobAuthorization().encryptedAuthData()).isNull();

    // API atomically updates job to from 'initial' to 'creds available'
    job =
        job.toBuilder()
            .setAndValidateJobAuthorization(
                job.jobAuthorization().toBuilder().setState(State.CREDS_AVAILABLE).build())
            .build();
    store.updateJobAuthStateToCredsAvailable(TEST_ID);

    // Verify 'creds available' state
    job = store.findJob(TEST_ID);
    assertThat(job.jobAuthorization().state()).isEqualTo(State.CREDS_AVAILABLE);
    // no auth data should exist yet
    assertThat(job.jobAuthorization().encryptedAuthData()).isNull();

    // Worker initiates the JobPollingService
    jobPollingService.runOneIteration();
    assertThat(JobMetadata.isInitialized()).isTrue();
    assertThat(JobMetadata.getJobId()).isEqualTo(TEST_ID);

    // Verify assigned without auth data state
    job = store.findJob(TEST_ID);
    assertThat(job.jobAuthorization().state())
        .isEqualTo(JobAuthorization.State.CREDS_ENCRYPTION_KEY_GENERATED);
    assertThat(job.jobAuthorization().authPublicKey()).isNotEmpty();

    // Client encrypts data and updates the job
    job =
        job.toBuilder()
            .setAndValidateJobAuthorization(
                job.jobAuthorization()
                    .toBuilder()
                    .setEncryptedAuthData("dummy export data")
                    .setState(State.CREDS_STORED)
                    .build())
            .build();
    store.updateJobWithCredentials(TEST_ID, job);

    // Run another iteration of the polling service
    // Worker should pick up encrypted data and update job
    jobPollingService.runOneIteration();
    job = store.findJob(TEST_ID);
    JobAuthorization jobAuthorization = job.jobAuthorization();
    assertThat(jobAuthorization.state()).isEqualTo(JobAuthorization.State.CREDS_STORED);
    assertThat(jobAuthorization.encryptedAuthData()).isNotEmpty();

    store.remove(TEST_ID);
  }