github.com/aacfactory/fns@v1.2.86-0.20240310083819-80d667fc0a17/services/service.go (about)

     1  /*
     2   * Copyright 2023 Wang Min Xiang
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   * 	http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   *
    16   */
    17  
    18  package services
    19  
    20  import (
    21  	"fmt"
    22  	"github.com/aacfactory/configures"
    23  	"github.com/aacfactory/errors"
    24  	"github.com/aacfactory/fns/commons/versions"
    25  	"github.com/aacfactory/fns/context"
    26  	"github.com/aacfactory/fns/services/documents"
    27  	"github.com/aacfactory/logs"
    28  	"sort"
    29  )
    30  
    31  type Options struct {
    32  	Id      string
    33  	Version versions.Version
    34  	Log     logs.Logger
    35  	Config  configures.Config
    36  }
    37  
    38  type Service interface {
    39  	Endpoint
    40  	Construct(options Options) (err error)
    41  	Components() (components Components)
    42  }
    43  
    44  type Listenable interface {
    45  	Service
    46  	// Listen
    47  	// ctx with runtime
    48  	Listen(ctx context.Context) (err error)
    49  }
    50  
    51  func NewAbstract(name string, internal bool, components ...Component) Abstract {
    52  	svc := Abstract{
    53  		name:       name,
    54  		internal:   internal,
    55  		log:        nil,
    56  		components: make(Components, 0, 1),
    57  		functions:  make(Fns, 0, 1),
    58  	}
    59  	if components != nil && len(components) > 0 {
    60  		for _, component := range components {
    61  			if component == nil {
    62  				continue
    63  			}
    64  			svc.components = append(svc.components, component)
    65  		}
    66  	}
    67  	return svc
    68  }
    69  
    70  type Abstract struct {
    71  	id         string
    72  	name       string
    73  	version    versions.Version
    74  	internal   bool
    75  	log        logs.Logger
    76  	components Components
    77  	functions  Fns
    78  }
    79  
    80  func (abstract *Abstract) Construct(options Options) (err error) {
    81  	abstract.log = options.Log
    82  	abstract.id = options.Id
    83  	abstract.version = options.Version
    84  	if abstract.components != nil {
    85  		for _, component := range abstract.components {
    86  			config, hasConfig := options.Config.Node(component.Name())
    87  			if !hasConfig {
    88  				config, _ = configures.NewJsonConfig([]byte{'{', '}'})
    89  			}
    90  			constructErr := component.Construct(Options{
    91  				Id:      abstract.id,
    92  				Version: abstract.version,
    93  				Log:     abstract.log.With("component", component.Name()),
    94  				Config:  config,
    95  			})
    96  			if constructErr != nil {
    97  				if abstract.log.ErrorEnabled() {
    98  					abstract.log.Error().Caller().Cause(errors.Wrap(constructErr).WithMeta("component", component.Name())).Message("service: construct component failed")
    99  				}
   100  				err = errors.Warning(fmt.Sprintf("fns: %s construct failed", abstract.name)).WithMeta("service", abstract.name).WithCause(constructErr)
   101  				return
   102  			}
   103  			return
   104  		}
   105  	}
   106  	return
   107  }
   108  
   109  func (abstract *Abstract) Id() string {
   110  	return abstract.id
   111  }
   112  
   113  func (abstract *Abstract) Name() (name string) {
   114  	name = abstract.name
   115  	return
   116  }
   117  
   118  func (abstract *Abstract) Version() versions.Version {
   119  	return abstract.version
   120  }
   121  
   122  func (abstract *Abstract) Internal() (internal bool) {
   123  	internal = abstract.internal
   124  	return
   125  }
   126  
   127  func (abstract *Abstract) Components() (components Components) {
   128  	components = abstract.components
   129  	return
   130  }
   131  
   132  func (abstract *Abstract) Document() (document documents.Endpoint) {
   133  	return
   134  }
   135  
   136  func (abstract *Abstract) AddFunction(fn Fn) {
   137  	abstract.functions = abstract.functions.Add(fn)
   138  	sort.Sort(abstract.functions)
   139  }
   140  
   141  func (abstract *Abstract) Functions() (functions Fns) {
   142  	functions = abstract.functions
   143  	return
   144  }
   145  
   146  func (abstract *Abstract) Shutdown(ctx context.Context) {
   147  	if abstract.components != nil && len(abstract.components) > 0 {
   148  		for _, component := range abstract.components {
   149  			component.Shutdown(ctx)
   150  		}
   151  	}
   152  	if abstract.log.DebugEnabled() {
   153  		abstract.log.Debug().Message(fmt.Sprintf("%s: closed", abstract.name))
   154  	}
   155  	return
   156  }
   157  
   158  func (abstract *Abstract) Log() (log logs.Logger) {
   159  	log = abstract.log
   160  	return
   161  }