github.com/ystia/yorc/v4@v4.3.0/plugin/context.go (about)

     1  // Copyright 2018 Bull S.A.S. Atos Technologies - Bull, Rue Jean Jaures, B.P.68, 78340, Les Clayes-sous-Bois, France.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package plugin
    16  
    17  import (
    18  	"context"
    19  	"net/rpc"
    20  	"time"
    21  
    22  	plugin "github.com/hashicorp/go-plugin"
    23  	"github.com/pkg/errors"
    24  
    25  	"github.com/ystia/yorc/v4/log"
    26  )
    27  
    28  func clientMonitorContextCancellation(ctx context.Context, closeChan chan struct{}, id uint32, broker *plugin.MuxBroker) {
    29  	var dialFailed bool
    30  RETRY:
    31  	conn, err := broker.Dial(id)
    32  	if err != nil {
    33  		if !dialFailed {
    34  			log.Printf("[ERROR] Failed to dial plugin %+v \nLet's retry until we succeed or the execution terminate. This that cancellation may not work.", errors.WithStack(err))
    35  		}
    36  		dialFailed = true
    37  		select {
    38  		case <-closeChan:
    39  			return
    40  		case <-time.After(500 * time.Millisecond):
    41  			goto RETRY
    42  		}
    43  	}
    44  	if dialFailed {
    45  		log.Printf("Plugin remote context cancellation dial finally succeeded after failures. Things are back to normal.")
    46  	}
    47  	client := rpc.NewClient(conn)
    48  	defer client.Close()
    49  
    50  	select {
    51  	case <-ctx.Done():
    52  		client.Call("Plugin.CancelContext", new(interface{}), &CancelContextResponse{})
    53  	case <-closeChan:
    54  	}
    55  }
    56  
    57  // RPCContextCanceller is public for use by reflexion and should be considered as private to this package.
    58  // Please do not use it directly.
    59  type RPCContextCanceller struct {
    60  	CancelFunc context.CancelFunc
    61  }
    62  
    63  // CancelContextResponse is public for use by reflexion and should be considered as private to this package.
    64  // Please do not use it directly.
    65  type CancelContextResponse struct{}
    66  
    67  // CancelContext is public for use by reflexion and should be considered as private to this package.
    68  // Please do not use it directly.
    69  func (r *RPCContextCanceller) CancelContext(nothing interface{}, resp *CancelContextResponse) error {
    70  	r.CancelFunc()
    71  	return nil
    72  }