Ejemplo n.º 1
0
func (attempt *attempt) Finish(data map[string]interface{}) error {
	globalLock(attempt)
	defer globalUnlock(attempt)
	if attempt.status != coordinate.Failed && !attempt.isPending() {
		return coordinate.ErrNotPending
	}
	attempt.finish(coordinate.Finished, data)

	// Does the work unit data include an "output" key that we
	// understand?
	if attempt.workUnit.activeAttempt != attempt {
		return nil
	}
	if data == nil {
		data = attempt.data
	}
	if data == nil {
		data = attempt.workUnit.data
	}
	var newUnits map[string]coordinate.AddWorkUnitItem
	var nextWorkSpec *workSpec
	output, ok := data["output"]
	if ok {
		newUnits = coordinate.ExtractWorkUnitOutput(output)
	}
	if newUnits != nil {
		then := attempt.workUnit.workSpec.meta.NextWorkSpecName
		if then != "" {
			nextWorkSpec, ok = attempt.workUnit.workSpec.namespace.workSpecs[then]
			nextWorkSpec.addWorkUnits(newUnits)
		}
	}

	return nil
}
Ejemplo n.º 2
0
func (a *attempt) Finish(data map[string]interface{}) error {
	return withTx(a, func(tx *sql.Tx) error {
		err := a.complete(tx, data, "finished")
		if err != nil {
			return err
		}

		// Does the work unit data include an "output" key
		// that we understand?  We may need to ring back to
		// the work unit here; we need the next work spec name
		// too in any case
		outputs := []string{workSpecNextWorkSpec, workUnitAttempt}
		tables := []string{workSpecTable, workUnitTable}
		conditions := []string{isWorkUnit, workUnitInSpec}
		if data == nil {
			outputs = append(outputs, workUnitData, attemptData)
			tables = append(tables, attemptTable)
			conditions = append(conditions, attemptThisWorkUnit)
		}
		query := buildSelect(outputs, tables, conditions)

		row := tx.QueryRow(query, a.unit.id)
		var attemptID sql.NullInt64
		var nextWorkSpec string
		if data == nil {
			var unitData, attemptData []byte
			err = row.Scan(&nextWorkSpec, &attemptID, &unitData, &attemptData)
			if err == nil {
				if attemptData != nil {
					data, err = bytesToMap(attemptData)
				} else if unitData != nil {
					data, err = bytesToMap(unitData)
				} else {
					data = map[string]interface{}{}
				}
			}
		} else {
			err = row.Scan(&nextWorkSpec, &attemptID)
		}
		if err != nil {
			return err
		}
		if nextWorkSpec == "" {
			return nil // nothing to do
		}
		if !attemptID.Valid || (attemptID.Int64 != int64(a.id)) {
			return nil // no longer active attempt
		}

		// TODO(dmaze): This should become a join in the
		// previous query
		query = buildSelect([]string{
			workSpecID,
		}, []string{
			workSpecTable,
		}, []string{
			inThisNamespace,
			workSpecName + "=$2",
		})
		row = tx.QueryRow(query, a.unit.spec.namespace.id, nextWorkSpec)
		var nextWorkSpecID int
		err = row.Scan(&nextWorkSpecID)
		if err != nil {
			return err
		}

		units := coordinate.ExtractWorkUnitOutput(data["output"])
		if units == nil {
			return nil // nothing to do
		}
		for name, item := range units {
			var dataBytes []byte
			dataBytes, err = mapToBytes(item.Data)
			if err != nil {
				return err
			}
			_, err = tx.Exec("INSERT INTO "+workUnitTable+"(work_spec_id, name, data, priority) VALUES ($1, $2, $3, $4)", nextWorkSpecID, name, dataBytes, item.Priority)
			if err != nil {
				return err
			}
		}

		return nil
	})
}