This is an automated email from the ASF dual-hosted git repository.

chaokunyang pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/fory.git


The following commit(s) were added to refs/heads/main by this push:
     new a23b1cef7 refactor(go): Replace globalTypeResolver with factory-based 
serializer registration (#2615)
a23b1cef7 is described below

commit a23b1cef7f121cae024806fc108b5e48d747170c
Author: thisingl <[email protected]>
AuthorDate: Tue Sep 16 14:01:40 2025 +0800

    refactor(go): Replace globalTypeResolver with factory-based serializer 
registration (#2615)
    
    <!--
    **Thanks for contributing to Apache Fory™.**
    
    **If this is your first time opening a PR on fory, you can refer to
    
[CONTRIBUTING.md](https://github.com/apache/fory/blob/main/CONTRIBUTING.md).**
    
    Contribution Checklist
    
    - The **Apache Fory™** community has requirements on the naming of pr
    titles. You can also find instructions in
    [CONTRIBUTING.md](https://github.com/apache/fory/blob/main/CONTRIBUTING.md).
    
    - Apache Fory™ has a strong focus on performance. If the PR you submit
    will have an impact on performance, please benchmark it first and
    provide the benchmark result here.
    -->
    
    ## Why?
    
    The current `globalTypeResolver` design has several issues:
    - Maintains complex dual state management (global + per-instance)
    - Every Fory instance creation requires copying entire global state
    
    
    ## What does this PR do?
    Replaced the complex global state management with a lightweight factory
    function registry
    <!-- Describe the details of this PR. -->
    #### Before (Complex Global State)
    ```go
    // Heavy global state with full serializer instances
    var globalTypeResolver *typeResolver
    
    // Every instance copies all global state
    func NewFory() {
        for type_, serializer := range globalTypeResolver.typeToSerializers {
            fory.typeResolver.typeToSerializers[type_] = serializer  // Full 
copy
        }
    }
    ```
    
    #### After (Lightweight Factory Registry)
    ```go
    // Lightweight global registry storing only factory functions
    var generatedSerializerFactories = struct {
        factories map[reflect.Type]func() Serializer
    }
    
    // Instance-level registration on demand
    func newTypeResolver() {
        for type_, factory := range generatedSerializerFactories.factories {
            serializer := factory()                          // Create on demand
            r.typeToSerializers[type_] = serializer         // Register to 
instance
        }
    }
    ```
    ## Related issues
    
    <!--
    Is there any related issue? If this PR closes them you say say
    fix/closes:
    
    - #xxxx0
    - #xxxx1
    - Fixes #xxxx2
    -->
    
    ## Does this PR introduce any user-facing change?
    
    <!--
    If any user-facing interface changes, please [open an
    issue](https://github.com/apache/fory/issues/new/choose) describing the
    need to do so and update the document if necessary.
    
    Delete section if not applicable.
    -->
    
    - [ ] Does this PR introduce any public API change?
    - [ ] Does this PR introduce any binary protocol compatibility change?
    
    ## Benchmark
    
    <!--
    When the PR has an impact on performance (if you don't know whether the
    PR will have an impact on performance, you can submit the PR first, and
    if it will have impact on performance, the code reviewer will explain
    it), be sure to attach a benchmark data here.
    
    Delete section if not applicable.
    -->
---
 go/fory/codegen/generator.go |  13 +++--
 go/fory/fory.go              |  26 +---------
 go/fory/type.go              | 121 ++++++++++---------------------------------
 3 files changed, 37 insertions(+), 123 deletions(-)

diff --git a/go/fory/codegen/generator.go b/go/fory/codegen/generator.go
index a2c236685..db50c0374 100644
--- a/go/fory/codegen/generator.go
+++ b/go/fory/codegen/generator.go
@@ -307,10 +307,10 @@ func generateCodeForFile(pkg *packages.Package, structs 
[]*StructInfo, sourceFil
        fmt.Fprintf(&buf, "\t\"github.com/apache/fory/go/fory\"\n")
        fmt.Fprintf(&buf, ")\n\n")
 
-       // Generate init function to register serializers
+       // Generate init function to register serializer factories
        fmt.Fprintf(&buf, "func init() {\n")
        for _, s := range structs {
-               fmt.Fprintf(&buf, 
"\tfory.RegisterGeneratedSerializer((*%s)(nil), %s_ForyGenSerializer{})\n", 
s.Name, s.Name)
+               fmt.Fprintf(&buf, "\tfory.RegisterSerializerFactory((*%s)(nil), 
NewSerializerFor_%s)\n", s.Name, s.Name)
        }
        fmt.Fprintf(&buf, "}\n\n")
 
@@ -393,6 +393,11 @@ func generateStructSerializer(buf *bytes.Buffer, s 
*StructInfo) error {
        // Generate struct serializer type
        fmt.Fprintf(buf, "type %s_ForyGenSerializer struct {}\n\n", s.Name)
 
+       // Generate factory function
+       fmt.Fprintf(buf, "func NewSerializerFor_%s() fory.Serializer {\n", 
s.Name)
+       fmt.Fprintf(buf, "\treturn %s_ForyGenSerializer{}\n", s.Name)
+       fmt.Fprintf(buf, "}\n\n")
+
        // Generate TypeId method
        fmt.Fprintf(buf, "func (%s_ForyGenSerializer) TypeId() fory.TypeId 
{\n", s.Name)
        fmt.Fprintf(buf, "\treturn fory.NAMED_STRUCT\n")
@@ -462,10 +467,10 @@ func generateCode(pkg *packages.Package, structs 
[]*StructInfo) error {
        fmt.Fprintf(&buf, "\t\"github.com/apache/fory/go/fory\"\n")
        fmt.Fprintf(&buf, ")\n\n")
 
-       // Generate init function to register serializers
+       // Generate init function to register serializer factories
        fmt.Fprintf(&buf, "func init() {\n")
        for _, s := range structs {
-               fmt.Fprintf(&buf, 
"\tfory.RegisterGeneratedSerializer((*%s)(nil), %s_ForyGenSerializer{})\n", 
s.Name, s.Name)
+               fmt.Fprintf(&buf, "\tfory.RegisterSerializerFactory((*%s)(nil), 
NewSerializerFor_%s)\n", s.Name, s.Name)
        }
        fmt.Fprintf(&buf, "}\n\n")
 
diff --git a/go/fory/fory.go b/go/fory/fory.go
index dbc81d584..becca516d 100644
--- a/go/fory/fory.go
+++ b/go/fory/fory.go
@@ -31,31 +31,7 @@ func NewFory(referenceTracking bool) *Fory {
                language:          XLANG,
                buffer:            NewByteBuffer(nil),
        }
-       // Create a new type resolver for this instance but copy generated 
serializers from global resolver
-       fory.typeResolver = newTypeResolver(fory)
-
-       // Copy generated serializers from global resolver to this instance
-       if globalTypeResolver != nil {
-               for type_, serializer := range 
globalTypeResolver.typeToSerializers {
-                       fory.typeResolver.typeToSerializers[type_] = serializer
-               }
-               for typeId, type_ := range globalTypeResolver.typeIdToType {
-                       fory.typeResolver.typeIdToType[typeId] = type_
-               }
-       }
-
-       return fory
-}
-
-// NewForyWithIsolatedTypes creates a Fory instance with isolated type resolver
-// for use cases that need independent type registration
-func NewForyWithIsolatedTypes(referenceTracking bool) *Fory {
-       fory := &Fory{
-               refResolver:       newRefResolver(referenceTracking),
-               referenceTracking: referenceTracking,
-               language:          XLANG,
-               buffer:            NewByteBuffer(nil),
-       }
+       // Create a new type resolver for this instance
        fory.typeResolver = newTypeResolver(fory)
        return fory
 }
diff --git a/go/fory/type.go b/go/fory/type.go
index af30a6dc1..8d1bc68f8 100644
--- a/go/fory/type.go
+++ b/go/fory/type.go
@@ -24,6 +24,7 @@ import (
        "regexp"
        "strconv"
        "strings"
+       "sync"
        "time"
 
        "github.com/apache/fory/go/fory/meta"
@@ -225,71 +226,24 @@ var (
        genericSetType     = reflect.TypeOf((*GenericSet)(nil)).Elem()
 )
 
-// Global type resolver shared by all Fory instances for generated serializers
-var globalTypeResolver *typeResolver
-
-func init() {
-       // Initialize global type resolver after other init functions
-       initGlobalTypeResolver()
+// Global registry for generated serializer factories
+var generatedSerializerFactories = struct {
+       mu        sync.RWMutex
+       factories map[reflect.Type]func() Serializer
+}{
+       factories: make(map[reflect.Type]func() Serializer),
 }
 
-func initGlobalTypeResolver() {
-       // Create a dummy fory instance just for initializing the global type 
resolver
-       r := &typeResolver{
-               typeTagToSerializers: map[string]Serializer{},
-               typeToSerializers:    map[reflect.Type]Serializer{},
-               typeIdToType:         map[int16]reflect.Type{},
-               typeToTypeInfo:       map[reflect.Type]string{},
-               typeInfoToType:       map[string]reflect.Type{},
-               dynamicStringToId:    map[string]int16{},
-               dynamicIdToString:    map[int16]string{},
-
-               language:            XLANG,
-               metaStringResolver:  NewMetaStringResolver(),
-               requireRegistration: false,
-
-               metaStrToStr:     make(map[string]string),
-               metaStrToClass:   make(map[string]reflect.Type),
-               hashToMetaString: make(map[uint64]string),
-               hashToClassInfo:  make(map[uint64]TypeInfo),
-
-               dynamicWrittenMetaStr: make([]string, 0),
-               typeIDToTypeInfo:      make(map[int32]TypeInfo),
-               typeIDCounter:         300,
-               dynamicWriteStringID:  0,
-
-               typesInfo:           make(map[reflect.Type]TypeInfo),
-               nsTypeToTypeInfo:    make(map[nsTypeKey]TypeInfo),
-               namedTypeToTypeInfo: make(map[namedTypeKey]TypeInfo),
-
-               namespaceEncoder: meta.NewEncoder('.', '_'),
-               namespaceDecoder: meta.NewDecoder('.', '_'),
-               typeNameEncoder:  meta.NewEncoder('$', '_'),
-               typeNameDecoder:  meta.NewDecoder('$', '_'),
+// RegisterSerializerFactory registers a factory function for a generated 
serializer
+func RegisterSerializerFactory(type_ interface{}, factory func() Serializer) {
+       reflectType := reflect.TypeOf(type_)
+       if reflectType.Kind() == reflect.Ptr {
+               reflectType = reflectType.Elem()
        }
 
-       // Initialize base type mappings - copy from newTypeResolver
-       for _, t := range []reflect.Type{
-               boolType,
-               byteType,
-               int8Type,
-               int16Type,
-               int32Type,
-               intType,
-               int64Type,
-               float32Type,
-               float64Type,
-               stringType,
-               dateType,
-               timestampType,
-               interfaceType,
-               genericSetType,
-       } {
-               r.typeInfoToType[t.String()] = t
-               r.typeToTypeInfo[t] = t.String()
-       }
-       r.initialize()
-       globalTypeResolver = r
+       generatedSerializerFactories.mu.Lock()
+       defer generatedSerializerFactories.mu.Unlock()
+       generatedSerializerFactories.factories[reflectType] = factory
 }
 
 type TypeInfo struct {
@@ -410,6 +364,18 @@ func newTypeResolver(fory *Fory) *typeResolver {
                r.typeToTypeInfo[t] = t.String()
        }
        r.initialize()
+
+       // Register generated serializers from factories
+       generatedSerializerFactories.mu.RLock()
+       for type_, factory := range generatedSerializerFactories.factories {
+               serializer := factory()
+               r.typeToSerializers[type_] = serializer
+               if typeId := serializer.TypeId(); typeId > 
NotSupportCrossLanguage {
+                       r.typeIdToType[typeId] = type_
+               }
+       }
+       generatedSerializerFactories.mu.RUnlock()
+
        return r
 }
 
@@ -469,39 +435,6 @@ func (r *typeResolver) RegisterSerializer(type_ 
reflect.Type, s Serializer) erro
        return nil
 }
 
-// RegisterGeneratedSerializer registers a generated serializer for a specific 
type.
-// Generated serializers have priority over reflection-based serializers and 
can override existing ones.
-func RegisterGeneratedSerializer(type_ interface{}, s Serializer) error {
-       if type_ == nil {
-               return fmt.Errorf("type_ cannot be nil")
-       }
-
-       reflectType := reflect.TypeOf(type_)
-       if reflectType.Kind() == reflect.Ptr {
-               reflectType = reflectType.Elem()
-       }
-
-       // Use the global type resolver
-       if globalTypeResolver == nil {
-               return fmt.Errorf("global type resolver not initialized")
-       }
-
-       // Allow overriding existing serializers by directly setting the map
-       // This gives generated serializers priority over reflection-based ones
-       globalTypeResolver.typeToSerializers[reflectType] = s
-
-       // Handle typeId registration
-       typeId := s.TypeId()
-       if typeId != FORY_TYPE_TAG {
-               if typeId > NotSupportCrossLanguage {
-                       // Allow overriding existing typeId mappings as well
-                       globalTypeResolver.typeIdToType[typeId] = reflectType
-               }
-       }
-
-       return nil
-}
-
 func (r *typeResolver) RegisterTypeTag(value reflect.Value, tag string) error {
        type_ := value.Type()
        if prev, ok := r.typeToSerializers[type_]; ok {


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to