 9bdcbe0447
			
		
	
	9bdcbe0447
	
	
	
		
			
			Major integrations and fixes: - Added BACKBEAT SDK integration for P2P operation timing - Implemented beat-aware status tracking for distributed operations - Added Docker secrets support for secure license management - Resolved KACHING license validation via HTTPS/TLS - Updated docker-compose configuration for clean stack deployment - Disabled rollback policies to prevent deployment failures - Added license credential storage (CHORUS-DEV-MULTI-001) Technical improvements: - BACKBEAT P2P operation tracking with phase management - Enhanced configuration system with file-based secrets - Improved error handling for license validation - Clean separation of KACHING and CHORUS deployment stacks 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
		
			
				
	
	
		
			157 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			157 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // Copyright (c) 2019 Uber Technologies, Inc.
 | |
| //
 | |
| // Permission is hereby granted, free of charge, to any person obtaining a copy
 | |
| // of this software and associated documentation files (the "Software"), to deal
 | |
| // in the Software without restriction, including without limitation the rights
 | |
| // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | |
| // copies of the Software, and to permit persons to whom the Software is
 | |
| // furnished to do so, subject to the following conditions:
 | |
| //
 | |
| // The above copyright notice and this permission notice shall be included in
 | |
| // all copies or substantial portions of the Software.
 | |
| //
 | |
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | |
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | |
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | |
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | |
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | |
| // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | |
| // THE SOFTWARE.
 | |
| 
 | |
| package fx
 | |
| 
 | |
| import (
 | |
| 	"fmt"
 | |
| 	"reflect"
 | |
| 	"unicode"
 | |
| 	"unicode/utf8"
 | |
| )
 | |
| 
 | |
| var _typeOfIn = reflect.TypeOf(In{})
 | |
| 
 | |
| // Extract fills the given struct with values from the dependency injection
 | |
| // container on application initialization. The target MUST be a pointer to a
 | |
| // struct. Only exported fields will be filled.
 | |
| //
 | |
| // Deprecated: Use Populate instead.
 | |
| func Extract(target interface{}) Option {
 | |
| 	v := reflect.ValueOf(target)
 | |
| 
 | |
| 	if t := v.Type(); t.Kind() != reflect.Ptr || t.Elem().Kind() != reflect.Struct {
 | |
| 		return Error(fmt.Errorf("Extract expected a pointer to a struct, got a %v", t))
 | |
| 	}
 | |
| 
 | |
| 	v = v.Elem()
 | |
| 	t := v.Type()
 | |
| 
 | |
| 	// We generate a function which accepts a single fx.In struct as an
 | |
| 	// argument. This struct contains all exported fields of the target
 | |
| 	// struct.
 | |
| 
 | |
| 	// Fields of the generated fx.In struct.
 | |
| 	fields := make([]reflect.StructField, 0, t.NumField()+1)
 | |
| 
 | |
| 	// Anonymous dig.In field.
 | |
| 	fields = append(fields, reflect.StructField{
 | |
| 		Name:      _typeOfIn.Name(),
 | |
| 		Anonymous: true,
 | |
| 		Type:      _typeOfIn,
 | |
| 	})
 | |
| 
 | |
| 	// List of values in the target struct aligned with the fields of the
 | |
| 	// generated struct.
 | |
| 	//
 | |
| 	// So for example, if the target is,
 | |
| 	//
 | |
| 	// 	var target struct {
 | |
| 	// 		Foo io.Reader
 | |
| 	// 		bar []byte
 | |
| 	// 		Baz io.Writer
 | |
| 	// 	}
 | |
| 	//
 | |
| 	// The generated struct has the shape,
 | |
| 	//
 | |
| 	// 	struct {
 | |
| 	// 		fx.In
 | |
| 	//
 | |
| 	// 		F0 io.Reader
 | |
| 	// 		F2 io.Writer
 | |
| 	// 	}
 | |
| 	//
 | |
| 	// And `targets` is,
 | |
| 	//
 | |
| 	// 	[
 | |
| 	// 		target.Field(0),  // Foo io.Reader
 | |
| 	// 		target.Field(2),  // Baz io.Writer
 | |
| 	// 	]
 | |
| 	//
 | |
| 	// As we iterate through the fields of the generated struct, we can copy
 | |
| 	// the value into the corresponding value in the targets list.
 | |
| 	targets := make([]reflect.Value, 0, t.NumField())
 | |
| 
 | |
| 	for i := 0; i < t.NumField(); i++ {
 | |
| 		f := t.Field(i)
 | |
| 
 | |
| 		// Skip unexported fields.
 | |
| 		if f.Anonymous {
 | |
| 			// If embedded, StructField.PkgPath is not a reliable indicator of
 | |
| 			// whether the field is exported. See
 | |
| 			// https://github.com/golang/go/issues/21122
 | |
| 
 | |
| 			t := f.Type
 | |
| 			if t.Kind() == reflect.Ptr {
 | |
| 				t = t.Elem()
 | |
| 			}
 | |
| 
 | |
| 			if !isExported(t.Name()) {
 | |
| 				continue
 | |
| 			}
 | |
| 		} else if f.PkgPath != "" {
 | |
| 			continue
 | |
| 		}
 | |
| 
 | |
| 		// We don't copy over names or embedded semantics.
 | |
| 		fields = append(fields, reflect.StructField{
 | |
| 			Name: fmt.Sprintf("F%d", i),
 | |
| 			Type: f.Type,
 | |
| 			Tag:  f.Tag,
 | |
| 		})
 | |
| 		targets = append(targets, v.Field(i))
 | |
| 	}
 | |
| 
 | |
| 	// Equivalent to,
 | |
| 	//
 | |
| 	// 	func(r struct {
 | |
| 	// 		fx.In
 | |
| 	//
 | |
| 	// 		F1 Foo
 | |
| 	// 		F2 Bar
 | |
| 	// 	}) {
 | |
| 	// 		target.Foo = r.F1
 | |
| 	// 		target.Bar = r.F2
 | |
| 	// 	}
 | |
| 
 | |
| 	fn := reflect.MakeFunc(
 | |
| 		reflect.FuncOf(
 | |
| 			[]reflect.Type{reflect.StructOf(fields)},
 | |
| 			nil,   /* results */
 | |
| 			false, /* variadic */
 | |
| 		),
 | |
| 		func(args []reflect.Value) []reflect.Value {
 | |
| 			result := args[0]
 | |
| 			for i := 1; i < result.NumField(); i++ {
 | |
| 				targets[i-1].Set(result.Field(i))
 | |
| 			}
 | |
| 			return nil
 | |
| 		},
 | |
| 	)
 | |
| 
 | |
| 	return Invoke(fn.Interface())
 | |
| }
 | |
| 
 | |
| // isExported reports whether the identifier is exported.
 | |
| func isExported(id string) bool {
 | |
| 	r, _ := utf8.DecodeRuneInString(id)
 | |
| 	return unicode.IsUpper(r)
 | |
| }
 |