Skip to content

Commit 9ff33f0

Browse files
committed
remove Gob encoder
1 parent 967004e commit 9ff33f0

File tree

5 files changed

+15
-232
lines changed

5 files changed

+15
-232
lines changed

dbos/client.go

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -239,22 +239,7 @@ func Enqueue[P any, R any](c Client, queueName, workflowName string, input P, op
239239
if c == nil {
240240
return nil, errors.New("client cannot be nil")
241241
}
242-
243-
// Register the input and outputs for gob encoding
244-
var logger *slog.Logger
245-
var serializer Serializer
246-
if cl, ok := c.(*client); ok {
247-
if ctx, ok := cl.dbosCtx.(*dbosContext); ok {
248-
logger = ctx.logger
249-
serializer = ctx.serializer
250-
}
251-
}
252-
var typedInput P
253-
var typedOutput R
254-
if isGobSerializer(serializer) {
255-
safeGobRegister(typedInput, logger)
256-
safeGobRegister(typedOutput, logger)
257-
}
242+
258243

259244
// Call the interface method with the same signature
260245
handle, err := c.Enqueue(queueName, workflowName, input, opts...)

dbos/dbos.go

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ func processConfig(inputConfig *Config) (*Config, error) {
7878
dbosConfig.DatabaseSchema = _DEFAULT_SYSTEM_DB_SCHEMA
7979
}
8080
if dbosConfig.Serializer == nil {
81-
dbosConfig.Serializer = NewGobSerializer()
81+
dbosConfig.Serializer = NewJSONSerializer()
8282
}
8383

8484
// Override with environment variables if set
@@ -370,15 +370,7 @@ func NewDBOSContext(ctx context.Context, inputConfig Config) (DBOSContext, error
370370
initExecutor.executorID = config.ExecutorID
371371
initExecutor.serializer = config.Serializer
372372

373-
// Register types we serialize with gob (only if using GobSerializer)
374-
if isGobSerializer(initExecutor.serializer) {
375-
var t time.Time
376-
safeGobRegister(t, initExecutor.logger)
377-
var ws []WorkflowStatus
378-
safeGobRegister(ws, initExecutor.logger)
379-
var si []StepInfo
380-
safeGobRegister(si, initExecutor.logger)
381-
}
373+
382374

383375
initExecutor.applicationID = os.Getenv("DBOS__APPID")
384376

dbos/serialization.go

Lines changed: 0 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,10 @@
11
package dbos
22

33
import (
4-
"bytes"
54
"encoding/base64"
6-
"encoding/gob"
75
"encoding/json"
86
"fmt"
9-
"log/slog"
107
"reflect"
11-
"strings"
128
)
139

1410
// Serializer defines the interface for pluggable serializers.
@@ -20,53 +16,6 @@ type Serializer interface {
2016
Decode(data *string) (any, error)
2117
}
2218

23-
// GobSerializer implements Serializer using encoding/gob
24-
type GobSerializer struct{}
25-
26-
func NewGobSerializer() *GobSerializer {
27-
return &GobSerializer{}
28-
}
29-
30-
// Encode serializes data using gob and encodes it to a base64 string
31-
// Performs "lazy" registration of the type with gob
32-
func (g *GobSerializer) Encode(data any) (string, error) {
33-
var inputBytes []byte
34-
if !isNilValue(data) {
35-
// Register the type with gob for proper serialization
36-
// This is useful when dealing with interface types that didn't have a concrete value at workflow registration time
37-
safeGobRegister(data, nil)
38-
39-
var buf bytes.Buffer
40-
enc := gob.NewEncoder(&buf)
41-
if err := enc.Encode(&data); err != nil {
42-
return "", fmt.Errorf("failed to encode data: %w", err)
43-
}
44-
inputBytes = buf.Bytes()
45-
}
46-
return base64.StdEncoding.EncodeToString(inputBytes), nil
47-
}
48-
49-
// Decode deserializes data from a base64 string using gob
50-
func (g *GobSerializer) Decode(data *string) (any, error) {
51-
if data == nil || *data == "" {
52-
return nil, nil
53-
}
54-
55-
dataBytes, err := base64.StdEncoding.DecodeString(*data)
56-
if err != nil {
57-
return nil, fmt.Errorf("failed to decode data: %w", err)
58-
}
59-
60-
var result any
61-
buf := bytes.NewBuffer(dataBytes)
62-
dec := gob.NewDecoder(buf)
63-
if err := dec.Decode(&result); err != nil {
64-
return nil, fmt.Errorf("failed to decode data: %w", err)
65-
}
66-
67-
return result, nil
68-
}
69-
7019
// JSONSerializer implements Serializer using encoding/json
7120
type JSONSerializer struct{}
7221

@@ -123,12 +72,6 @@ func isJSONSerializer(s Serializer) bool {
12372
return ok
12473
}
12574

126-
// isGobSerializer checks if the given serializer is a GobSerializer
127-
func isGobSerializer(s Serializer) bool {
128-
_, ok := s.(*GobSerializer)
129-
return ok
130-
}
131-
13275
// convertJSONToType converts a JSON-decoded value (map[string]interface{}) to type T
13376
// via marshal/unmarshal round-trip.
13477
//
@@ -145,8 +88,6 @@ func convertJSONToType[T any](value any) (T, error) {
14588
return *new(T), fmt.Errorf("marshaling for type conversion: %w", err)
14689
}
14790

148-
fmt.Println("convertJSONToType:", string(jsonBytes))
149-
15091
// Check if T is an interface type
15192
var zero T
15293
typeOfT := reflect.TypeOf(&zero).Elem()
@@ -194,28 +135,3 @@ func isNilValue(data any) bool {
194135
}
195136
return false
196137
}
197-
198-
// safeGobRegister attempts to register a type with gob, recovering only from
199-
// panics caused by duplicate type/name registrations (e.g., registering both T and *T).
200-
// These specific conflicts don't affect encoding/decoding correctness, so they're safe to ignore.
201-
// Other panics (like register `any`) are real errors and will propagate.
202-
func safeGobRegister(value any, logger *slog.Logger) {
203-
defer func() {
204-
if r := recover(); r != nil {
205-
if errStr, ok := r.(string); ok {
206-
// Check if this is one of the two specific duplicate registration errors we want to ignore
207-
// See https://cs.opensource.google/go/go/+/refs/tags/go1.25.1:src/encoding/gob/type.go;l=832
208-
if strings.Contains(errStr, "gob: registering duplicate types for") ||
209-
strings.Contains(errStr, "gob: registering duplicate names for") {
210-
if logger != nil {
211-
logger.Debug("gob registration conflict", "type", fmt.Sprintf("%T", value), "error", r)
212-
}
213-
return
214-
}
215-
}
216-
// Re-panic for any other errors
217-
panic(r)
218-
}
219-
}()
220-
gob.Register(value)
221-
}

dbos/serialization_test.go

Lines changed: 10 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -553,7 +553,6 @@ func serializerAnyRecoveryWorkflow(ctx DBOSContext, input any) (any, error) {
553553
func TestSerializer(t *testing.T) {
554554
serializers := map[string]func() Serializer{
555555
"JSON": func() Serializer { return NewJSONSerializer() },
556-
"Gob": func() Serializer { return NewGobSerializer() },
557556
}
558557

559558
for serializerName, serializerFactory := range serializers {
@@ -573,15 +572,13 @@ func TestSerializer(t *testing.T) {
573572
RegisterWorkflow(executor, serializerGetEventWorkflow)
574573
RegisterWorkflow(executor, serializerRecoveryWorkflow)
575574
RegisterWorkflow(executor, serializerInterfaceValueWorkflow)
576-
if serializerName == "JSON" {
577-
// Cannot register "any" workflow with Gob serializer
578-
RegisterWorkflow(executor, serializerAnyValueWorkflow)
579-
RegisterWorkflow(executor, serializerAnySenderWorkflow)
580-
RegisterWorkflow(executor, serializerAnyReceiverWorkflow)
581-
RegisterWorkflow(executor, serializerAnySetEventWorkflow)
582-
RegisterWorkflow(executor, serializerAnyGetEventWorkflow)
583-
RegisterWorkflow(executor, serializerAnyRecoveryWorkflow)
584-
}
575+
// Register any-type workflows (JSON-only runtime)
576+
RegisterWorkflow(executor, serializerAnyValueWorkflow)
577+
RegisterWorkflow(executor, serializerAnySenderWorkflow)
578+
RegisterWorkflow(executor, serializerAnyReceiverWorkflow)
579+
RegisterWorkflow(executor, serializerAnySetEventWorkflow)
580+
RegisterWorkflow(executor, serializerAnyGetEventWorkflow)
581+
RegisterWorkflow(executor, serializerAnyRecoveryWorkflow)
585582

586583
err := Launch(executor)
587584
require.NoError(t, err)
@@ -606,9 +603,6 @@ func TestSerializer(t *testing.T) {
606603

607604
// Test workflow with any type and comprehensive data structure
608605
t.Run("ComprehensiveAnyValues", func(t *testing.T) {
609-
if serializerName == "Gob" {
610-
t.Skip("Skipping test for Gob serializer due to Gob limitations with interface types")
611-
}
612606
input := TestWorkflowData{
613607
ID: "any-test-id",
614608
Message: "any test message",
@@ -697,9 +691,6 @@ func TestSerializer(t *testing.T) {
697691

698692
// Test nil values with any type workflow
699693
t.Run("NilValuesAny", func(t *testing.T) {
700-
if serializerName == "Gob" {
701-
t.Skip("Skipping test for Gob serializer due to Gob limitations with interface types")
702-
}
703694
handle, err := RunWorkflow(executor, serializerAnyValueWorkflow, nil)
704695
require.NoError(t, err, "Nil any workflow execution failed")
705696

@@ -769,9 +760,6 @@ func TestSerializer(t *testing.T) {
769760

770761
// Test Send/Recv with any type
771762
t.Run("SendRecvAny", func(t *testing.T) {
772-
if serializerName == "Gob" {
773-
t.Skip("Skipping test for Gob serializer due to Gob limitations with interface types")
774-
}
775763
input := TestWorkflowData{
776764
ID: "sendrecv-any-test-id",
777765
Message: "any test message",
@@ -786,9 +774,6 @@ func TestSerializer(t *testing.T) {
786774

787775
// Test SetEvent/GetEvent with any type
788776
t.Run("SetGetEventAny", func(t *testing.T) {
789-
if serializerName == "Gob" {
790-
t.Skip("Skipping test for Gob serializer due to Gob limitations with interface types")
791-
}
792777
input := TestWorkflowData{
793778
ID: "event-any-test-id",
794779
Message: "any event message",
@@ -820,9 +805,6 @@ func TestSerializer(t *testing.T) {
820805

821806
// Test workflow recovery with any type
822807
t.Run("WorkflowRecoveryAny", func(t *testing.T) {
823-
if serializerName == "Gob" {
824-
t.Skip("Skipping test for Gob serializer due to Gob limitations with interface types")
825-
}
826808

827809
serializerAnyRecoveryStartEvent = NewEvent()
828810
serializerAnyRecoveryEvent = NewEvent()
@@ -862,9 +844,6 @@ func TestSerializer(t *testing.T) {
862844

863845
// Test queued workflow with any type
864846
t.Run("QueuedWorkflowAny", func(t *testing.T) {
865-
if serializerName == "Gob" {
866-
t.Skip("Skipping test for Gob serializer due to Gob limitations with interface types")
867-
}
868847

869848
input := TestWorkflowData{
870849
ID: "queued-any-test-id",
@@ -896,7 +875,6 @@ func TestSerializer(t *testing.T) {
896875
// Test serializer interface compliance
897876
func TestSerializerInterface(t *testing.T) {
898877
// Test that both serializers implement the Serializer interface
899-
var _ Serializer = (*GobSerializer)(nil)
900878
var _ Serializer = (*JSONSerializer)(nil)
901879
}
902880

@@ -920,25 +898,9 @@ func TestSerializerConfiguration(t *testing.T) {
920898
}
921899
})
922900

923-
// Test Gob serializer configuration
924-
t.Run("GobSerializer", func(t *testing.T) {
925-
config := Config{
926-
DatabaseURL: getDatabaseURL(),
927-
AppName: "test-app",
928-
Serializer: NewGobSerializer(),
929-
}
930-
931-
executor, err := NewDBOSContext(context.Background(), config)
932-
require.NoError(t, err, "Failed to create DBOS context with Gob serializer")
933-
934-
// Verify the serializer is set in the context
935-
if dbosCtx, ok := executor.(*dbosContext); ok {
936-
assert.NotNil(t, dbosCtx.serializer, "Gob serializer should be configured")
937-
assert.IsType(t, &GobSerializer{}, dbosCtx.serializer, "Should be GobSerializer type")
938-
}
939-
})
901+
// Removed Gob serializer configuration test
940902

941-
// Test default serializer (should be Gob)
903+
// Test default serializer (should be JSON)
942904
t.Run("DefaultSerializer", func(t *testing.T) {
943905
config := Config{
944906
DatabaseURL: getDatabaseURL(),
@@ -952,7 +914,7 @@ func TestSerializerConfiguration(t *testing.T) {
952914
// Verify the default serializer is Gob
953915
if dbosCtx, ok := executor.(*dbosContext); ok {
954916
assert.NotNil(t, dbosCtx.serializer, "Default serializer should be configured")
955-
assert.IsType(t, &GobSerializer{}, dbosCtx.serializer, "Default should be GobSerializer")
917+
assert.IsType(t, &JSONSerializer{}, dbosCtx.serializer, "Default should be JSONSerializer")
956918
}
957919
})
958920
}

0 commit comments

Comments
 (0)