github.com/getgauge/gauge@v1.6.9/plugin/handler.go (about)

     1  /*----------------------------------------------------------------
     2   *  Copyright (c) ThoughtWorks, Inc.
     3   *  Licensed under the Apache License, Version 2.0
     4   *  See LICENSE in the project root for license information.
     5   *----------------------------------------------------------------*/
     6  
     7  package plugin
     8  
     9  import (
    10  	"sync"
    11  
    12  	"github.com/getgauge/gauge-proto/go/gauge_messages"
    13  	"github.com/getgauge/gauge/logger"
    14  )
    15  
    16  // Handler manages plugins listed in project manifest.
    17  type Handler interface {
    18  	NotifyPlugins(*gauge_messages.Message)
    19  	GracefullyKillPlugins()
    20  }
    21  
    22  // GaugePlugins holds a reference to all plugins launched. The plugins are listed in project manifest
    23  type GaugePlugins struct {
    24  	pluginsMap map[string]*plugin
    25  }
    26  
    27  func (gp *GaugePlugins) addPlugin(pluginID string, pluginToAdd *plugin) {
    28  	if gp.pluginsMap == nil {
    29  		gp.pluginsMap = make(map[string]*plugin)
    30  	}
    31  	gp.pluginsMap[pluginID] = pluginToAdd
    32  }
    33  
    34  func (gp *GaugePlugins) removePlugin(pluginID string) {
    35  	delete(gp.pluginsMap, pluginID)
    36  }
    37  
    38  // NotifyPlugins passes a message to all plugins listed in the manifest
    39  func (gp *GaugePlugins) NotifyPlugins(message *gauge_messages.Message) {
    40  	var handle = func(id string, p *plugin, err error) {
    41  		if err != nil {
    42  			logger.Errorf(true, "Unable to connect to plugin %s %s. %s\n", p.descriptor.Name, p.descriptor.Version, err.Error())
    43  			gp.killPlugin(id)
    44  		}
    45  	}
    46  
    47  	for id, plugin := range gp.pluginsMap {
    48  		handle(id, plugin, plugin.sendMessage(message))
    49  	}
    50  }
    51  
    52  func (gp *GaugePlugins) killPlugin(pluginID string) {
    53  	plugin := gp.pluginsMap[pluginID]
    54  	logger.Debugf(true, "Killing Plugin %s %s\n", plugin.descriptor.Name, plugin.descriptor.Version)
    55  	err := plugin.pluginCmd.Process.Kill()
    56  	if err != nil {
    57  		logger.Errorf(true, "Failed to kill plugin %s %s. %s\n", plugin.descriptor.Name, plugin.descriptor.Version, err.Error())
    58  	}
    59  	gp.removePlugin(pluginID)
    60  }
    61  
    62  // GracefullyKillPlugins tells the plugins to stop, letting them cleanup whatever they need to
    63  func (gp *GaugePlugins) GracefullyKillPlugins() {
    64  	var wg sync.WaitGroup
    65  	for _, pl := range gp.pluginsMap {
    66  		wg.Add(1)
    67  		logger.Debugf(true, "Sending kill message to %s plugin.", pl.descriptor.Name)
    68  		go func(p *plugin) {
    69  			err := p.kill(&wg)
    70  			if err != nil {
    71  				logger.Errorf(false, "Unable to kill plugin %s : %s", p.descriptor.Name, err.Error())
    72  			}
    73  		}(pl)
    74  	}
    75  	wg.Wait()
    76  }