134 lines
3.9 KiB
Go
134 lines
3.9 KiB
Go
|
// Copyright 2015 Google Inc. All Rights Reserved.
|
||
|
//
|
||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
// you may not use this file except in compliance with the License.
|
||
|
// You may obtain a copy of the License at
|
||
|
//
|
||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||
|
//
|
||
|
// Unless required by applicable law or agreed to in writing, software
|
||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
// See the License for the specific language governing permissions and
|
||
|
// limitations under the License.
|
||
|
|
||
|
package bigquery
|
||
|
|
||
|
import (
|
||
|
"cloud.google.com/go/internal"
|
||
|
gax "github.com/googleapis/gax-go"
|
||
|
"golang.org/x/net/context"
|
||
|
bq "google.golang.org/api/bigquery/v2"
|
||
|
)
|
||
|
|
||
|
// A Job represents an operation which has been submitted to BigQuery for processing.
|
||
|
type Job struct {
|
||
|
service service
|
||
|
projectID string
|
||
|
jobID string
|
||
|
|
||
|
isQuery bool
|
||
|
}
|
||
|
|
||
|
// JobFromID creates a Job which refers to an existing BigQuery job. The job
|
||
|
// need not have been created by this package. For example, the job may have
|
||
|
// been created in the BigQuery console.
|
||
|
func (c *Client) JobFromID(ctx context.Context, id string) (*Job, error) {
|
||
|
jobType, err := c.service.getJobType(ctx, c.projectID, id)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
return &Job{
|
||
|
service: c.service,
|
||
|
projectID: c.projectID,
|
||
|
jobID: id,
|
||
|
isQuery: jobType == queryJobType,
|
||
|
}, nil
|
||
|
}
|
||
|
|
||
|
func (j *Job) ID() string {
|
||
|
return j.jobID
|
||
|
}
|
||
|
|
||
|
// State is one of a sequence of states that a Job progresses through as it is processed.
|
||
|
type State int
|
||
|
|
||
|
const (
|
||
|
Pending State = iota
|
||
|
Running
|
||
|
Done
|
||
|
)
|
||
|
|
||
|
// JobStatus contains the current State of a job, and errors encountered while processing that job.
|
||
|
type JobStatus struct {
|
||
|
State State
|
||
|
|
||
|
err error
|
||
|
|
||
|
// All errors encountered during the running of the job.
|
||
|
// Not all Errors are fatal, so errors here do not necessarily mean that the job has completed or was unsuccessful.
|
||
|
Errors []*Error
|
||
|
}
|
||
|
|
||
|
// setJobRef initializes job's JobReference if given a non-empty jobID.
|
||
|
// projectID must be non-empty.
|
||
|
func setJobRef(job *bq.Job, jobID, projectID string) {
|
||
|
if jobID == "" {
|
||
|
return
|
||
|
}
|
||
|
// We don't check whether projectID is empty; the server will return an
|
||
|
// error when it encounters the resulting JobReference.
|
||
|
|
||
|
job.JobReference = &bq.JobReference{
|
||
|
JobId: jobID,
|
||
|
ProjectId: projectID,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Done reports whether the job has completed.
|
||
|
// After Done returns true, the Err method will return an error if the job completed unsuccesfully.
|
||
|
func (s *JobStatus) Done() bool {
|
||
|
return s.State == Done
|
||
|
}
|
||
|
|
||
|
// Err returns the error that caused the job to complete unsuccesfully (if any).
|
||
|
func (s *JobStatus) Err() error {
|
||
|
return s.err
|
||
|
}
|
||
|
|
||
|
// Status returns the current status of the job. It fails if the Status could not be determined.
|
||
|
func (j *Job) Status(ctx context.Context) (*JobStatus, error) {
|
||
|
return j.service.jobStatus(ctx, j.projectID, j.jobID)
|
||
|
}
|
||
|
|
||
|
// Cancel requests that a job be cancelled. This method returns without waiting for
|
||
|
// cancellation to take effect. To check whether the job has terminated, use Job.Status.
|
||
|
// Cancelled jobs may still incur costs.
|
||
|
func (j *Job) Cancel(ctx context.Context) error {
|
||
|
return j.service.jobCancel(ctx, j.projectID, j.jobID)
|
||
|
}
|
||
|
|
||
|
// Wait blocks until the job or th context is done. It returns the final status
|
||
|
// of the job.
|
||
|
// If an error occurs while retrieving the status, Wait returns that error. But
|
||
|
// Wait returns nil if the status was retrieved successfully, even if
|
||
|
// status.Err() != nil. So callers must check both errors. See the example.
|
||
|
func (j *Job) Wait(ctx context.Context) (*JobStatus, error) {
|
||
|
var js *JobStatus
|
||
|
err := internal.Retry(ctx, gax.Backoff{}, func() (stop bool, err error) {
|
||
|
js, err = j.Status(ctx)
|
||
|
if err != nil {
|
||
|
return true, err
|
||
|
}
|
||
|
if js.Done() {
|
||
|
return true, nil
|
||
|
}
|
||
|
return false, nil
|
||
|
})
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
return js, nil
|
||
|
}
|