 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>
		
			
				
	
	
		
			202 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			202 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package hscan
 | |
| 
 | |
| import (
 | |
| 	"errors"
 | |
| 	"fmt"
 | |
| 	"reflect"
 | |
| 	"strconv"
 | |
| )
 | |
| 
 | |
| // decoderFunc represents decoding functions for default built-in types.
 | |
| type decoderFunc func(reflect.Value, string) error
 | |
| 
 | |
| var (
 | |
| 	// List of built-in decoders indexed by their numeric constant values (eg: reflect.Bool = 1).
 | |
| 	decoders = []decoderFunc{
 | |
| 		reflect.Bool:          decodeBool,
 | |
| 		reflect.Int:           decodeInt,
 | |
| 		reflect.Int8:          decodeInt8,
 | |
| 		reflect.Int16:         decodeInt16,
 | |
| 		reflect.Int32:         decodeInt32,
 | |
| 		reflect.Int64:         decodeInt64,
 | |
| 		reflect.Uint:          decodeUint,
 | |
| 		reflect.Uint8:         decodeUint8,
 | |
| 		reflect.Uint16:        decodeUint16,
 | |
| 		reflect.Uint32:        decodeUint32,
 | |
| 		reflect.Uint64:        decodeUint64,
 | |
| 		reflect.Float32:       decodeFloat32,
 | |
| 		reflect.Float64:       decodeFloat64,
 | |
| 		reflect.Complex64:     decodeUnsupported,
 | |
| 		reflect.Complex128:    decodeUnsupported,
 | |
| 		reflect.Array:         decodeUnsupported,
 | |
| 		reflect.Chan:          decodeUnsupported,
 | |
| 		reflect.Func:          decodeUnsupported,
 | |
| 		reflect.Interface:     decodeUnsupported,
 | |
| 		reflect.Map:           decodeUnsupported,
 | |
| 		reflect.Ptr:           decodeUnsupported,
 | |
| 		reflect.Slice:         decodeSlice,
 | |
| 		reflect.String:        decodeString,
 | |
| 		reflect.Struct:        decodeUnsupported,
 | |
| 		reflect.UnsafePointer: decodeUnsupported,
 | |
| 	}
 | |
| 
 | |
| 	// Global map of struct field specs that is populated once for every new
 | |
| 	// struct type that is scanned. This caches the field types and the corresponding
 | |
| 	// decoder functions to avoid iterating through struct fields on subsequent scans.
 | |
| 	globalStructMap = newStructMap()
 | |
| )
 | |
| 
 | |
| func Struct(dst interface{}) (StructValue, error) {
 | |
| 	v := reflect.ValueOf(dst)
 | |
| 
 | |
| 	// The destination to scan into should be a struct pointer.
 | |
| 	if v.Kind() != reflect.Ptr || v.IsNil() {
 | |
| 		return StructValue{}, fmt.Errorf("redis.Scan(non-pointer %T)", dst)
 | |
| 	}
 | |
| 
 | |
| 	v = v.Elem()
 | |
| 	if v.Kind() != reflect.Struct {
 | |
| 		return StructValue{}, fmt.Errorf("redis.Scan(non-struct %T)", dst)
 | |
| 	}
 | |
| 
 | |
| 	return StructValue{
 | |
| 		spec:  globalStructMap.get(v.Type()),
 | |
| 		value: v,
 | |
| 	}, nil
 | |
| }
 | |
| 
 | |
| // Scan scans the results from a key-value Redis map result set to a destination struct.
 | |
| // The Redis keys are matched to the struct's field with the `redis` tag.
 | |
| func Scan(dst interface{}, keys []interface{}, vals []interface{}) error {
 | |
| 	if len(keys) != len(vals) {
 | |
| 		return errors.New("args should have the same number of keys and vals")
 | |
| 	}
 | |
| 
 | |
| 	strct, err := Struct(dst)
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	// Iterate through the (key, value) sequence.
 | |
| 	for i := 0; i < len(vals); i++ {
 | |
| 		key, ok := keys[i].(string)
 | |
| 		if !ok {
 | |
| 			continue
 | |
| 		}
 | |
| 
 | |
| 		val, ok := vals[i].(string)
 | |
| 		if !ok {
 | |
| 			continue
 | |
| 		}
 | |
| 
 | |
| 		if err := strct.Scan(key, val); err != nil {
 | |
| 			return err
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func decodeBool(f reflect.Value, s string) error {
 | |
| 	b, err := strconv.ParseBool(s)
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 	f.SetBool(b)
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func decodeInt8(f reflect.Value, s string) error {
 | |
| 	return decodeNumber(f, s, 8)
 | |
| }
 | |
| 
 | |
| func decodeInt16(f reflect.Value, s string) error {
 | |
| 	return decodeNumber(f, s, 16)
 | |
| }
 | |
| 
 | |
| func decodeInt32(f reflect.Value, s string) error {
 | |
| 	return decodeNumber(f, s, 32)
 | |
| }
 | |
| 
 | |
| func decodeInt64(f reflect.Value, s string) error {
 | |
| 	return decodeNumber(f, s, 64)
 | |
| }
 | |
| 
 | |
| func decodeInt(f reflect.Value, s string) error {
 | |
| 	return decodeNumber(f, s, 0)
 | |
| }
 | |
| 
 | |
| func decodeNumber(f reflect.Value, s string, bitSize int) error {
 | |
| 	v, err := strconv.ParseInt(s, 10, bitSize)
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 	f.SetInt(v)
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func decodeUint8(f reflect.Value, s string) error {
 | |
| 	return decodeUnsignedNumber(f, s, 8)
 | |
| }
 | |
| 
 | |
| func decodeUint16(f reflect.Value, s string) error {
 | |
| 	return decodeUnsignedNumber(f, s, 16)
 | |
| }
 | |
| 
 | |
| func decodeUint32(f reflect.Value, s string) error {
 | |
| 	return decodeUnsignedNumber(f, s, 32)
 | |
| }
 | |
| 
 | |
| func decodeUint64(f reflect.Value, s string) error {
 | |
| 	return decodeUnsignedNumber(f, s, 64)
 | |
| }
 | |
| 
 | |
| func decodeUint(f reflect.Value, s string) error {
 | |
| 	return decodeUnsignedNumber(f, s, 0)
 | |
| }
 | |
| 
 | |
| func decodeUnsignedNumber(f reflect.Value, s string, bitSize int) error {
 | |
| 	v, err := strconv.ParseUint(s, 10, bitSize)
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 	f.SetUint(v)
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func decodeFloat32(f reflect.Value, s string) error {
 | |
| 	v, err := strconv.ParseFloat(s, 32)
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 	f.SetFloat(v)
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // although the default is float64, but we better define it.
 | |
| func decodeFloat64(f reflect.Value, s string) error {
 | |
| 	v, err := strconv.ParseFloat(s, 64)
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 	f.SetFloat(v)
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func decodeString(f reflect.Value, s string) error {
 | |
| 	f.SetString(s)
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func decodeSlice(f reflect.Value, s string) error {
 | |
| 	// []byte slice ([]uint8).
 | |
| 	if f.Type().Elem().Kind() == reflect.Uint8 {
 | |
| 		f.SetBytes([]byte(s))
 | |
| 	}
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func decodeUnsupported(v reflect.Value, s string) error {
 | |
| 	return fmt.Errorf("redis.Scan(unsupported %s)", v.Type())
 | |
| }
 |