github.com/pavlo67/common@v0.5.3/common/joiner/joiner_runtime/runtime.go (about)

     1  package joiner_runtime
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  	"reflect"
     7  	"sync"
     8  
     9  	"github.com/pkg/errors"
    10  
    11  	"github.com/pavlo67/common/common"
    12  	"github.com/pavlo67/common/common/joiner"
    13  	"github.com/pavlo67/common/common/logger"
    14  )
    15  
    16  var _ joiner.Operator = &joinerRuntime{}
    17  
    18  func New(options common.Map, l logger.Operator) joiner.Operator {
    19  	return &joinerRuntime{
    20  		l:          l,
    21  		options:    options,
    22  		components: map[joiner.InterfaceKey]interface{}{},
    23  		mutex:      &sync.RWMutex{},
    24  	}
    25  }
    26  
    27  type joinerRuntime struct {
    28  	l          logger.Operator
    29  	options    common.Map
    30  	components map[joiner.InterfaceKey]interface{}
    31  	mutex      *sync.RWMutex
    32  }
    33  
    34  var ErrJoiningOnEmptyKey = errors.New("can't join on empty interface key")
    35  var ErrJoiningNil = errors.New("can't join nil interface")
    36  var ErrJoiningDuplicate = errors.New("can't join interface over joined before")
    37  
    38  func (j *joinerRuntime) Join(intrfc interface{}, interfaceKey joiner.InterfaceKey) error {
    39  	if j == nil {
    40  		return fmt.Errorf("got nil on .Join(%s)", interfaceKey)
    41  	}
    42  	if interfaceKey == "" {
    43  		return errors.Wrapf(ErrJoiningNil, "on .Join(%s)", interfaceKey)
    44  	}
    45  	if intrfc == nil {
    46  		return errors.Wrapf(ErrJoiningNil, "on .Join(%s)", interfaceKey)
    47  	}
    48  
    49  	j.mutex.Lock()
    50  	defer j.mutex.Unlock()
    51  
    52  	if _, ok := j.components[interfaceKey]; ok {
    53  		return errors.Wrapf(ErrJoiningDuplicate, "on .Join(%s)", interfaceKey)
    54  	}
    55  
    56  	j.components[interfaceKey] = intrfc
    57  
    58  	if j.l != nil && !j.options.IsTrue("silent") {
    59  		j.l.Infof("joined (%T) as %s", intrfc, interfaceKey)
    60  	}
    61  
    62  	return nil
    63  }
    64  
    65  func (j *joinerRuntime) Interface(interfaceKey joiner.InterfaceKey) interface{} {
    66  	if j == nil {
    67  		log.Printf("on ActorKey.Component(%s): null ActorKey item", interfaceKey)
    68  	}
    69  
    70  	j.mutex.RLock()
    71  	defer j.mutex.RUnlock()
    72  
    73  	if intrfc, ok := j.components[interfaceKey]; ok {
    74  		return intrfc
    75  	}
    76  
    77  	return nil
    78  }
    79  
    80  func (j *joinerRuntime) InterfacesAll(ptrToInterface interface{}) []joiner.Component {
    81  	j.mutex.RLock()
    82  	defer j.mutex.RUnlock()
    83  
    84  	var components []joiner.Component
    85  
    86  	for key, intrfc := range j.components {
    87  		if CheckInterface(intrfc, ptrToInterface) {
    88  			components = append(components, joiner.Component{InterfaceKey: key, Interface: intrfc})
    89  		}
    90  	}
    91  
    92  	return components
    93  }
    94  
    95  func CheckInterface(intrfc interface{}, ptrToInterface interface{}) bool {
    96  	defer func() {
    97  		recover()
    98  	}()
    99  
   100  	// ??? reflect.TypeOf(ptrToInterface).Elem()
   101  	// ??? if intrfc != nil
   102  	if reflect.TypeOf(intrfc).Implements(reflect.TypeOf(ptrToInterface).Elem()) {
   103  		return true
   104  	}
   105  
   106  	return false
   107  }
   108  
   109  func (j *joinerRuntime) CloseAll() {
   110  	if j == nil {
   111  		log.Print("on ActorKey.Close(): null ActorKey item")
   112  		return
   113  	}
   114  
   115  	closerComponents := j.InterfacesAll((*joiner.Closer)(nil))
   116  
   117  	for _, closerComponent := range closerComponents {
   118  		if closer, _ := closerComponent.Interface.(joiner.Closer); closer != nil {
   119  			err := closer.Close()
   120  			if err != nil {
   121  				log.Print("on ActorKey.Close(): ", err)
   122  			}
   123  		}
   124  	}
   125  
   126  }