github.com/hy3/cuto@v0.9.8-0.20160830082821-aa6652f877b7/db/tx/jobnettx.go (about)

     1  // Copyright 2015 unirita Inc.
     2  // Created 2015/04/10 shanxia
     3  
     4  package tx
     5  
     6  import (
     7  	"fmt"
     8  	"sync"
     9  
    10  	"github.com/unirita/cuto/db"
    11  	"github.com/unirita/cuto/db/query"
    12  	"github.com/unirita/cuto/log"
    13  	"github.com/unirita/cuto/utctime"
    14  )
    15  
    16  // ジョブIDをキーに持つ
    17  type JobMap map[string]*db.JobResult
    18  
    19  // ジョブ実行結果を保持する。
    20  type ResultMap struct {
    21  	JobnetResult *db.JobNetworkResult // ジョブネットワーク情報の構造体。
    22  	jobresults   JobMap               // ジョブネットワーク内のジョブ状態を保存するMap。
    23  	conn         db.IConnection       // DBコネクション
    24  }
    25  
    26  // ジョブネットワークの開始状態を記録する。
    27  //
    28  // param : jobnetName ジョブネットワーク名。
    29  //
    30  // param : dbname データベース名。
    31  //
    32  // return : ジョブ実行結果を保持する構造体ポインタ。
    33  //
    34  // return : error
    35  func StartJobNetwork(jobnetName string, dbname string) (*ResultMap, error) {
    36  	jn := db.NewJobNetworkResult(jobnetName, utctime.Now().String(), db.RUNNING)
    37  
    38  	conn, err := db.Open(dbname)
    39  	if err != nil {
    40  		return nil, err
    41  	}
    42  	resMap := &ResultMap{jn, make(JobMap), conn}
    43  
    44  	if err := resMap.insertJobNetwork(); err != nil {
    45  		return nil, err
    46  	}
    47  	return resMap, nil
    48  }
    49  
    50  // ジョブネットワークの実行結果を復元する。
    51  func ResumeJobNetwork(nid int, dbname string) (*ResultMap, error) {
    52  	conn, err := db.Open(dbname)
    53  	if err != nil {
    54  		return nil, err
    55  	}
    56  	jn, err := query.GetJobnetwork(conn, nid)
    57  	if err != nil {
    58  		return nil, err
    59  	}
    60  
    61  	jr, err := query.GetJobMapOfTargetNetwork(conn, nid)
    62  	if err != nil {
    63  		return nil, err
    64  	}
    65  
    66  	resMap := &ResultMap{
    67  		JobnetResult: jn,
    68  		jobresults:   jr,
    69  		conn:         conn,
    70  	}
    71  
    72  	return resMap, nil
    73  }
    74  
    75  // ネットワーク終了時に結果情報を設定する。同時にDBコネクションも切断する。
    76  //
    77  // param : status ジョブネットワークのステータス。
    78  //
    79  // param : detail ジョブネットワークに記録する詳細メッセージ。
    80  //
    81  // return : error
    82  func (r *ResultMap) EndJobNetwork(status int, detail string) error {
    83  	if r.conn == nil {
    84  		return fmt.Errorf("Can't access DB file.")
    85  	}
    86  	defer r.conn.Close()
    87  
    88  	if r.JobnetResult == nil {
    89  		return fmt.Errorf("Invalid Jobnetwork info.")
    90  	}
    91  	r.JobnetResult.EndDate = utctime.Now().String()
    92  	r.JobnetResult.Status = status
    93  	r.JobnetResult.Detail = detail
    94  
    95  	for _, jobresult := range r.jobresults {
    96  		if r.JobnetResult.Status < jobresult.Status {
    97  			r.JobnetResult.Status = jobresult.Status
    98  		}
    99  	}
   100  
   101  	if err := r.updateJobNetwork(); err != nil {
   102  		return err
   103  	}
   104  	return nil
   105  }
   106  
   107  // DBコネクションを返す。
   108  func (r *ResultMap) GetConnection() db.IConnection {
   109  	return r.conn
   110  }
   111  
   112  // ジョブネットワークレコードをInsertする。
   113  func (r *ResultMap) insertJobNetwork() error {
   114  	var isCommit bool
   115  	tx, err := r.conn.GetDbMap().Begin()
   116  	if err != nil {
   117  		return err
   118  	}
   119  	defer func() {
   120  		if !isCommit {
   121  			tx.Rollback()
   122  		}
   123  	}()
   124  
   125  	now := utctime.Now().String()
   126  	r.JobnetResult.CreateDate = now
   127  	r.JobnetResult.UpdateDate = now
   128  
   129  	err = tx.Insert(r.JobnetResult)
   130  	if err != nil {
   131  		return err
   132  	}
   133  	if err = tx.Commit(); err != nil {
   134  		return err
   135  	}
   136  	log.Debug(fmt.Sprintf("networkId[%v]", r.JobnetResult.ID))
   137  	isCommit = true
   138  	return nil
   139  }
   140  
   141  // ジョブネットワークレコードをUpdateする。
   142  func (r *ResultMap) updateJobNetwork() error {
   143  	var isCommit bool
   144  	tx, err := r.conn.GetDbMap().Begin()
   145  	if err != nil {
   146  		return err
   147  	}
   148  	defer func() {
   149  		if !isCommit {
   150  			tx.Rollback()
   151  		}
   152  	}()
   153  	r.JobnetResult.UpdateDate = utctime.Now().String()
   154  
   155  	if _, err = tx.Update(r.JobnetResult); err != nil {
   156  		return err
   157  	}
   158  	if err = tx.Commit(); err != nil {
   159  		return err
   160  	}
   161  	isCommit = true
   162  	return nil
   163  }
   164  
   165  // DBコネクションを外部から渡す。テスト用のメソッド。
   166  func (r *ResultMap) SetConnection(conn db.IConnection) {
   167  	r.conn = conn
   168  }
   169  
   170  var localMutex sync.Mutex // JobMap dedicated mutex.
   171  
   172  // getter JobResult
   173  func (r *ResultMap) GetJobResults(jobId string) (*db.JobResult, bool) {
   174  	res, exist := r.jobresults[jobId]
   175  	return res, exist
   176  }
   177  
   178  // setter JobResult. (thread safe)
   179  func (r *ResultMap) AddJobResults(jobId string, jobRes *db.JobResult) {
   180  	localMutex.Lock()
   181  	defer localMutex.Unlock()
   182  	r.jobresults[jobId] = jobRes
   183  }
   184  
   185  // test function
   186  func NewResultMap() *ResultMap {
   187  	return &ResultMap{
   188  		JobnetResult: nil,
   189  		jobresults:   make(JobMap),
   190  	}
   191  }