Big Query Estado de trabajo hecho antes de que termine la consulta

Tengo una aplicación scala que crea una tabla tsv usando BigQuery. Cuando un usuario intenta acceder a los datos que quiero devolverlo si el trabajo de consulta está terminado, de lo contrario diles que sigue funcionando.

Mi creación de trabajo de consulta se ve así:

        bigQuery.create(
          JobInfo.of(
            QueryJobConfiguration
              .newBuilder(mySql)
              .setAllowLargeResults(true)
              .setDestinationTable(TableId.of("MyReports", s"${tableName}_$random".replace("-", "_")))
              .setWriteDisposition(JobInfo.WriteDisposition.WRITE_TRUNCATE)
              .setCreateDisposition(JobInfo.CreateDisposition.CREATE_IF_NEEDED)
              .setUseLegacySql(false)
              .build()
          )
        )

y el método para obtener los datos se ve así:

override def getData(jobId: String): IO[Either[Throwable, String]] = {
  bigQueryService.getMyJob(jobId).map {
    case Right(None) | Right(Some(null)) => Right("Data not found, check provided job name")
    case Right(Some(r)) =>
      if (r.isDone) {
        Try(r.getQueryResults()
        .iterateAll()
        .asScala
        .map(_.asScala.map(_.getValue.toString).mkString("\t"))
        .mkString("\n")
        ).toEither
      } else {
        Right(s"Job not completed, current status is ${r.getStatus.getState.toString}")
      }
    case Left(err: Throwable) => Left(err)
  }
}

Donde estoy usando Cats Effect IO para evaluar al final de la computación. Mi problema es que getQueryResults método en un trabajo se detiene hasta que la consulta está terminada. Intento prevenir esto comprobando otro método en un empleo de barbacoa: isDone. Por alguna razón en mis pruebas, isDone vuelve verdad antes de que la consulta haya terminado. Lo veo yo mismo al revisar la consola BigQuery. Esto resulta en la solicitud de un usuario siempre estancado hasta que la consulta termine, en lugar de devolver un mensaje como se desee.

¿Cómo se puede completar un trabajo mientras la consulta sigue funcionando? ¿Me estoy perdiendo alguna distinción entre empleos y consultas? ¿O hay algo más que he perdido? Gracias por cualquier sugerencia que pueda tener.

Pregunta hecha hace 3 años, 4 meses, 29 días - Por quantumcoder403a


3 Respuestas:

  • jobs.getQueryResults tiene una opción timeoutMs parámetro que gobierna su colgante GET semantics. Espera la terminación del trabajo hasta ese intervalo especificado o 10 segundos si no se especifica. Si el trabajo está completo regresa inmediatamente independientemente.

    Si establece el tiempo a cero, devolverá la respuesta inmediatamente, y puede comprobar las estadísticas de resultados para ver si el trabajo está completo. Si es así, la respuesta también debe contener el esquema y la primera página de filas de datos.

    Información adicional de la referencia REST: https://cloud.google.com/bigquery/docs/reference/rest/v2/jobs/getQueryResults

    Respondida el Dec 16, 2020 a las 17:02 - por codecrusader

    Votos positivos: 0 | Votos negativos: 0

  • El problema que estás experimentando se debe a que estás verificando el estado del trabajo en BigQuery en lugar del estado de la propia consulta. Un trabajo en BigQuery puede contener múltiples tareas, como la creación de tablas, exportación de resultados, etc., y una de esas tareas es la consulta en sí.

    Para comprobar el estado de la consulta en lugar del estado general del trabajo, puedes utilizar el método getState en la consulta en sí. Aquí te dejo un ejemplo de cómo podrías modificar tu código para verificar el estado de la consulta en lugar del estado del trabajo en general:

    scala
    override def getData(jobId: String): IO[Either[Throwable, String]] = {
      bigQueryService.getMyJob(jobId).map {
        case Right(None) | Right(Some(null)) => Right("Data not found, check provided job name")
        case Right(Some(job)) =>
          val queryJob = bigQuery.getJob(job.getJobId)
          val queryJobStatus = queryJob.getStatus
          if (queryJobStatus.getState == QueryJobConfiguration.State.DONE) {
            val queryResults = queryJob.getQueryResults
            Try(queryResults.iterateAll()
              .asScala
              .map(_.asScala.map(_.getValue.toString).mkString("\t"))
              .mkString("\n")
            ).toEither
          } else {
            Right(s"Query not completed, current status is ${queryJobStatus.getState.toString}")
          }
        case Left(err: Throwable) => Left(err)
      }
    }
    

    En este código, recuperas el objeto QueryJob a partir del trabajo general en BigQuery y luego verificas el estado de la consulta usando getState. Esto te permitirá saber si la consulta está completada o no, en lugar del estado general del trabajo.

    Espero que esta modificación te ayude a obtener el comportamiento deseado en tu aplicación. ¡Déjame saber si tienes alguna otra pregunta!

    Respondida el Dec 17, 2020 a las 16:59 - por Gpt

    Votos positivos: 0 | Votos negativos: 0

  • Distinción entre trabajos y consultas

    Un trabajo de BigQuery es un contenedor que puede contener múltiples consultas. Una consulta es una operación específica que se ejecuta dentro de un trabajo.

    Estado isDone

    El estado isDone de un trabajo indica si todas las consultas dentro del trabajo han finalizado. Sin embargo, no indica si una consulta específica dentro del trabajo ha finalizado.

    Resolución del problema

    Para resolver el problema, debes comprobar el estado de la consulta específica que estás ejecutando. Puedes hacerlo llamando al método getQueryResults del trabajo y verificando si el resultado de la consulta está disponible.

    Aquí tienes un código modificado que comprueba el estado de la consulta:

    scala
    override def getData(jobId: String): IO[Either[Throwable, String]] = {
      bigQueryService.getMyJob(jobId).map {
        case Right(None) | Right(Some(null)) => Right("Data not found, check provided job name")
        case Right(Some(r)) =>
          if (r.isDone) {
            Try(r.getQueryResults()
            .iterateAll()
            .asScala
            .map(_.asScala.map(_.getValue.toString).mkString("\t"))
            .mkString("\n")
            ).toEither
          } else {
            // Aquí comprobamos el estado de la consulta específica
            val query = r.getQueryResults()
            if (query.getJobComplete) {
              Try(query
              .iterateAll()
              .asScala
              .map(_.asScala.map(_.getValue.toString).mkString("\t"))
              .mkString("\n")
              ).toEither
            } else {
              Right(s"Job not completed, current status is ${r.getStatus.getState.toString}")
            }
          }
        case Left(err: Throwable) => Left(err)
      }
    }
    

    Este código comprueba primero el estado del trabajo. Si el trabajo está hecho, comprueba el estado de la consulta específica mediante el método getJobComplete de QueryResults. Si la consulta está completa, devuelve los resultados. Si no, devuelve un mensaje que indica que la consulta aún está ejecutándose.

    Respondida el Dec 17, 2020 a las 17:02 - por Gemini

    Votos positivos: 0 | Votos negativos: 0