public function extract(Configuration $configuration, $params = [])
 {
     $this->writerService->setStorageApi($configuration->getStorageApi());
     $writer = $this->writerService->getWriter();
     $accounts = $configuration->getAccounts();
     if (isset($params['account']) || isset($params['config'])) {
         $accountId = isset($params['account']) ? $params['account'] : $params['config'];
         if (!isset($accounts[$accountId])) {
             throw new UserException("Account '" . $accountId . "' does not exist.");
         }
         $accounts = array($accountId => $accounts[$accountId]);
     }
     /** @var Account $account */
     foreach ($accounts as $account) {
         $outBucket = $account->getAttribute('outputBucket');
         if ($outBucket == null) {
             $outBucket = $configuration->initDataBucket($account->getAccountId());
         }
         $accountReports = $account->getReports();
         $reports = $accountReports;
         if (isset($params['report'])) {
             foreach ($accountReports as $report) {
                 if ($report['id'] == $params['report']) {
                     $reports = array($report);
                     break;
                 }
             }
         }
         foreach ($reports as $report) {
             $writerId = $this->writerService->getWriterByPid($report['pid']);
             $data = ['writerId' => $writerId, 'pid' => $report['pid'], 'report' => $report['uri'], 'table' => $outBucket . '.' . 'report-' . $report['id'], 'queue' => 'secondary'];
             if (isset($report['config'])) {
                 $reportConfig = json_decode($report['config'], true);
                 if (isset($reportConfig['username']) && isset($reportConfig['password'])) {
                     $data['username'] = $reportConfig['username'];
                     $data['password'] = $reportConfig['password'];
                 }
             }
             $request = $writer->post('/gooddata-writer/export-report', null, json_encode($data));
             $response = $request->send()->json();
             $jobId = $response['job'];
             // wait for job to finish
             $retries = 0;
             $job = null;
             sleep(rand(60, 120));
             while ($retries < 60) {
                 $job = $writer->getJob($jobId);
                 $this->logger->debug("Getting writers job", ['writerJob' => $job]);
                 if ($job['status'] == 'success' || $job['status'] == 'error') {
                     break;
                 }
                 sleep(rand(60, 120));
                 $retries++;
             }
             if (!isset($job['status']) || $job['status'] != 'success') {
                 if (isset($job['result']['message']) && strstr($job['result']['message'], 'User error') !== false) {
                     throw new UserException($job['result']['error'], null, ['params' => $job['parameters']]);
                 }
                 if (isset($job['result']['error']) && strstr($job['result']['error'], '404') !== false) {
                     throw new UserException("Report not found", null, ['params' => $job['parameters']]);
                 }
                 if (isset($job['result']['message']) && strstr($job['result']['message'], 'GoodData user does not have access to resource') !== false) {
                     throw new UserException("GoodData user does not have access to report", null, ['params' => $job['parameters']]);
                 }
                 throw new ApplicationException("Error processing writers job {$jobId}", null, ['writerJob' => $job]);
             }
         }
     }
     return array("status" => "ok");
 }