github.com/hy3/cuto@v0.9.8-0.20160830082821-aa6652f877b7/master/jobnet/gateway.go (about)

     1  package jobnet
     2  
     3  import "fmt"
     4  
     5  // ジョブネット内のフロー分岐・集約を表す構造体
     6  type Gateway struct {
     7  	id    string
     8  	Nexts []Element
     9  }
    10  
    11  // Gateway構造体のコンストラクタ関数
    12  func NewGateway(id string) *Gateway {
    13  	gateway := new(Gateway)
    14  	gateway.id = id
    15  	return gateway
    16  }
    17  
    18  // IDを取得する
    19  func (g *Gateway) ID() string {
    20  	return g.id
    21  }
    22  
    23  // ノードタイプを取得する
    24  //
    25  // return : ノードタイプ
    26  func (g *Gateway) Type() elementType {
    27  	return ELM_GW
    28  }
    29  
    30  // 後続エレメントの追加を行う。
    31  func (g *Gateway) AddNext(e Element) error {
    32  	g.Nexts = append(g.Nexts, e)
    33  	return nil
    34  }
    35  
    36  // 後続エレメントの有無を調べる。
    37  func (g *Gateway) HasNext() bool {
    38  	return len(g.Nexts) > 0
    39  }
    40  
    41  // 後続のノード数に応じて、ゲートウェイの処理を行う。
    42  //
    43  // 後続ノードが存在しない場合:何も行わない。次の実行ノードとしてnilを返す。
    44  //
    45  // 後続ノードが1つだけの場合:何も行わない。次の実行ノードとして唯一の後続ノードを返す。
    46  //
    47  // 後続ノードが2つ以上の場合:各後続ノードを先頭としたPath構造体を生成し、並列実行する。次の実行ノードとして結合ゲートウェイを返す。
    48  //
    49  // return : 次の実行ノード
    50  //
    51  // return : エラー情報
    52  func (g *Gateway) Execute() (Element, error) {
    53  	nextCnt := len(g.Nexts)
    54  
    55  	switch nextCnt {
    56  	case 0:
    57  		return nil, nil
    58  	case 1:
    59  		return g.Nexts[0], nil
    60  	default:
    61  		paths := make([]*Path, nextCnt)
    62  		done := make(chan struct{}, nextCnt)
    63  		for i := 0; i < nextCnt; i++ {
    64  			paths[i] = NewPath(g.Nexts[i])
    65  			go paths[i].Run(done)
    66  		}
    67  		for i := 0; i < nextCnt; i++ {
    68  			<-done
    69  		}
    70  		for i := 0; i < nextCnt; i++ {
    71  			if paths[i].Err != nil {
    72  				err := fmt.Errorf("Error occured in branch: %s", paths[i].Err)
    73  				return nil, err
    74  			}
    75  			if paths[i].Goal != paths[0].Goal {
    76  				err := fmt.Errorf("Branch is combined by more than one gateway.")
    77  				return nil, err
    78  			}
    79  		}
    80  		return paths[0].Goal, nil
    81  	}
    82  }