Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[perf] fix double serialization for continueAsNew input (IWF-140) #414

Open
longquanzheng opened this issue Aug 31, 2024 · 1 comment
Open

Comments

@longquanzheng
Copy link
Contributor

longquanzheng commented Aug 31, 2024

Right now the input is stored like this in the history:

[{"checksum":"\ufffd^\ufffd`\ufffd\ufffd\ufffd\ufffd\u0014_H\u0016\ufffd\ufffd\ufffd=","jsonData":"{\"StatesToStartFromBeginning\":[{\"stateId\":\"PersistRuleState\",\"stateInput\":{\"data\":\"{\\\"createdByUserId\\\":\\\"mwhitty\\\",\\\"shouldApplyToExistingJobs\\\":true,\\\"tagsToAdd\\\":[\\\"tag1\\\",\\\"tag2\\\"],\\\"statusToChange\\\":\\\"OPEN\\\",\\\"campaignToAdd\\\":\\\"CAMPAIGN-X\\\",\\\"ownerToChange\\\":\\\"qlong\\\",\\\"userIdsToNotify\\\":[\\\"user1\\\",\\\"user2\\\"],\\\"userIdsToGrantEditAccess\\\":[\\\"user3\\\",\\\"user4\\\"]}\",\"encoding\":\"springJackson\"}}],\"StateExecutionsToResume\":{},\"InterStateChannelReceived\":{},\"SignalsReceived\":{},\"StateExecutionCounterInfo\":{\"StateIdStartedCount\":{\"PersistRuleState\":50},\"StateIdCurrentlyExecutingCount\":{},\"TotalCurrentlyExecutingCount\":0},\"StateOutputs\":[],\"StaleSkipTimerSignals\":null,\"DataObjects\":[{\"key\":\"TotalPages\",\"value\":{\"data\":\"0\",\"encoding\":\"springJackson\"}}],\"SearchAttributes\":null}","totalPages":1}]

You can see a lot of \\ in it which is very wasteful and hard to read.

This is because this DumpWorkflowInternal activity has serialized the data that is already JSON serialized.

func DumpWorkflowInternal(

We need to improve this.


Spent two days into this, and realized that JSON is not going to work for saving the double serialization. This is because the data that we are storing is not valid JSON because of pagination, hence we cannot use json.RawMessage.

The best way is to use proto based serialization like gRPC.

Defer this for now until we know it's necessary to do this

@mixydubs mixydubs changed the title [perf] fix double serialization for continueAsNew input [perf] fix double serialization for continueAsNew input (IWF-140) Oct 31, 2024
@longquanzheng
Copy link
Contributor Author

Testing code when trying to override JSON mashal/unmashal, but didn't work:

package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"strings"
)

type MyResponse struct {
	JsonData1 string `json:"jsonData1"`
}

func (v MyResponse) MarshalJSON() ([]byte, error) {
	respCopy := v
	respCopy.JsonData1 = ""
	v0, err := json.Marshal(respCopy)
	if err != nil {
		return nil, err
	}
	return []byte(string(v0) + "&" + v.JsonData1), nil
}

func (v *MyResponse) UnmarshalJSON(src []byte) error {
	vs := strings.Split(string(src), "&")
	if len(vs) != 2 {
		panic("error in deserialization")
	}
	err := json.Unmarshal([]byte(vs[0]), &v)
	if err != nil {
		return err
	}
	v.JsonData1 = vs[1][1:]
	return nil
}

type SomeStruct struct {
	StringVal string `json:"stringVal"`
	IntVal    int    `json:"intVal"`
}

type EncodedObject struct {
	Encoding string `json:"encoding,omitempty"`
	Data     string `json:"data,omitempty"`
}

func main() {

	val0 := SomeStruct{
		StringVal: "aaaa|-$*&$",
		IntVal:    100,
	}

	encodedVal0, err := json.Marshal(val0)
	if err != nil {
		panic(err)
	}
	val00 := EncodedObject{
		Encoding: "json",
		Data:     string(encodedVal0),
	}
	encodedVal00, err := json.Marshal(val00)
	if err != nil {
		panic(err)
	}
	// {"data":"{\"stringVal\":\"aaaa\",\"intVal\":100}","encoding":"json"}
	fmt.Println(string(encodedVal00))

	val1 := MyResponse{
		JsonData1: string(encodedVal00[0:80]), // NOTE: for some reasons, I have to use part of it...(if you are interested, it is because of pagination)
	}

	b := new(bytes.Buffer)
	d := json.NewEncoder(b)
	d.SetEscapeHTML(false)
	err = d.Encode(val1)
	if err != nil {
		panic(err)
	}
	encodedVal1 := b.String()

	// {"jsonData1":"{\"encoding\":\"json\",\"data\":\"{\\\"stringVal\\\":\\\"aaaa\\\""}
	fmt.Println(encodedVal1)
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants