diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index cefd13b84113d1e2a1dc483104c11ea82a7e1819..f70c6360c2609120af3b32b7fad230c47e90d07e 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -69,9 +69,11 @@ build-workers: - GOOS=js GOARCH=wasm go build -ldflags '-w -s' -trimpath -o release/xxdk-channelsIndexedDkWorker.wasm ./indexedDb/impl/channels/... - GOOS=js GOARCH=wasm go build -ldflags '-w -s' -trimpath -o release/xxdk-dmIndexedDkWorker.wasm ./indexedDb/impl/dm/... - GOOS=js GOARCH=wasm go build -ldflags '-w -s' -trimpath -o release/xxdk-logFileWorker.wasm ./logging/workerThread/... + - GOOS=js GOARCH=wasm go build -ldflags '-w -s' -trimpath -o release/xxdk-stateIndexedDbWorker.wasm ./indexedDb/impl/state/... - cp indexedDb/impl/channels/channelsIndexedDbWorker.js release/ - cp indexedDb/impl/dm/dmIndexedDbWorker.js release/ - cp logging/workerThread/logFileWorker.js release/ + - cp indexedDb/impl/state/stateIndexedDbWorker.js release/ artifacts: paths: - release/ @@ -112,9 +114,11 @@ combine-artifacts: - 'curl --fail --location --header "PRIVATE-TOKEN: $GITLAB_ACCESS_TOKEN" --output release/xxdk-channelsIndexedDkWorker.wasm $CI_SERVER_URL/api/v4/projects/$CI_PROJECT_ID/jobs/$BUILD_WORKERS_JOB_ID/artifacts/release/xxdk-channelsIndexedDkWorker.wasm' - 'curl --fail --location --header "PRIVATE-TOKEN: $GITLAB_ACCESS_TOKEN" --output release/xxdk-dmIndexedDkWorker.wasm $CI_SERVER_URL/api/v4/projects/$CI_PROJECT_ID/jobs/$BUILD_WORKERS_JOB_ID/artifacts/release/xxdk-dmIndexedDkWorker.wasm' - 'curl --fail --location --header "PRIVATE-TOKEN: $GITLAB_ACCESS_TOKEN" --output release/xxdk-logFileWorker.wasm $CI_SERVER_URL/api/v4/projects/$CI_PROJECT_ID/jobs/$BUILD_WORKERS_JOB_ID/artifacts/release/xxdk-logFileWorker.wasm' + - 'curl --fail --location --header "PRIVATE-TOKEN: $GITLAB_ACCESS_TOKEN" --output release/xxdk-stateIndexedDbWorker.wasm $CI_SERVER_URL/api/v4/projects/$CI_PROJECT_ID/jobs/$BUILD_WORKERS_JOB_ID/artifacts/release/xxdk-stateIndexedDbWorker.wasm' - 'curl --fail --location --header "PRIVATE-TOKEN: $GITLAB_ACCESS_TOKEN" --output release/channelsIndexedDbWorker.js $CI_SERVER_URL/api/v4/projects/$CI_PROJECT_ID/jobs/$BUILD_WORKERS_JOB_ID/artifacts/release/channelsIndexedDbWorker.js' - 'curl --fail --location --header "PRIVATE-TOKEN: $GITLAB_ACCESS_TOKEN" --output release/dmIndexedDbWorker.js $CI_SERVER_URL/api/v4/projects/$CI_PROJECT_ID/jobs/$BUILD_WORKERS_JOB_ID/artifacts/release/dmIndexedDbWorker.js' - 'curl --fail --location --header "PRIVATE-TOKEN: $GITLAB_ACCESS_TOKEN" --output release/logFileWorker.js $CI_SERVER_URL/api/v4/projects/$CI_PROJECT_ID/jobs/$BUILD_WORKERS_JOB_ID/artifacts/release/logFileWorker.js' + - 'curl --fail --location --header "PRIVATE-TOKEN: $GITLAB_ACCESS_TOKEN" --output release/stateIndexedDbWorker.js $CI_SERVER_URL/api/v4/projects/$CI_PROJECT_ID/jobs/$BUILD_WORKERS_JOB_ID/artifacts/release/stateIndexedDbWorker.js' - ls release artifacts: paths: diff --git a/Makefile b/Makefile index 657afc891a3ecac25d132c699a30cc3f0e459940..cd183023d09da89d457b2f7a4ec08d33ab75db15 100644 --- a/Makefile +++ b/Makefile @@ -32,6 +32,7 @@ binary: worker_binaries: GOOS=js GOARCH=wasm go build -ldflags '-w -s' -trimpath -o xxdk-channelsIndexedDkWorker.wasm ./indexedDb/impl/channels/... GOOS=js GOARCH=wasm go build -ldflags '-w -s' -trimpath -o xxdk-dmIndexedDkWorker.wasm ./indexedDb/impl/dm/... + GOOS=js GOARCH=wasm go build -ldflags '-w -s' -trimpath -o xxdk-stateIndexedDkWorker.wasm ./indexedDb/impl/state/... GOOS=js GOARCH=wasm go build -ldflags '-w -s' -trimpath -o xxdk-logFileWorker.wasm ./logging/workerThread/... binaries: binary worker_binaries diff --git a/indexedDb/impl/channels/implementation.go b/indexedDb/impl/channels/implementation.go index f043c60be8b1c2b91931a466c1153ee2680ce07c..e755acbafb3f750e577305fb9e241c537f30febe 100644 --- a/indexedDb/impl/channels/implementation.go +++ b/indexedDb/impl/channels/implementation.go @@ -32,9 +32,7 @@ import ( "gitlab.com/xx_network/primitives/id" ) -// wasmModel implements [channels.EventModel] interface, which uses the channels -// system passed an object that adheres to in order to get events on the -// channel. +// wasmModel implements [channels.EventModel] interface backed by IndexedDb. // NOTE: This model is NOT thread safe - it is the responsibility of the // caller to ensure that its methods are called sequentially. type wasmModel struct { diff --git a/indexedDb/impl/channels/init.go b/indexedDb/impl/channels/init.go index 171175dd6bf4b2ab900068da18c4a10032c8b443..48f5359f9b61c67b42533a42fa37cec4c3c917e7 100644 --- a/indexedDb/impl/channels/init.go +++ b/indexedDb/impl/channels/init.go @@ -43,12 +43,13 @@ func newWASMModel(databaseName string, encryption cryptoChannel.Cipher, openRequest, err := idb.Global().Open(ctx, databaseName, currentVersion, func(db *idb.Database, oldVersion, newVersion uint) error { if oldVersion == newVersion { - jww.INFO.Printf("IndexDb version is current: v%d", newVersion) + jww.INFO.Printf("IndexDb version for %s is current: v%d", + databaseName, newVersion) return nil } - jww.INFO.Printf("IndexDb upgrade required: v%d -> v%d", - oldVersion, newVersion) + jww.INFO.Printf("IndexDb upgrade required for %s: v%d -> v%d", + databaseName, oldVersion, newVersion) if oldVersion == 0 && newVersion >= 1 { err := v1Upgrade(db) diff --git a/indexedDb/impl/dm/init.go b/indexedDb/impl/dm/init.go index f99f4ef3e2d7f46f9a5672c8ea998c4afdbe1a77..8332866b95055e7d322308cdf8669d1be78a95ac 100644 --- a/indexedDb/impl/dm/init.go +++ b/indexedDb/impl/dm/init.go @@ -49,12 +49,13 @@ func newWASMModel(databaseName string, encryption cryptoChannel.Cipher, openRequest, err := idb.Global().Open(ctx, databaseName, currentVersion, func(db *idb.Database, oldVersion, newVersion uint) error { if oldVersion == newVersion { - jww.INFO.Printf("IndexDb version is current: v%d", newVersion) + jww.INFO.Printf("IndexDb version for %s is current: v%d", + databaseName, newVersion) return nil } - jww.INFO.Printf("IndexDb upgrade required: v%d -> v%d", - oldVersion, newVersion) + jww.INFO.Printf("IndexDb upgrade required for %s: v%d -> v%d", + databaseName, oldVersion, newVersion) if oldVersion == 0 && newVersion >= 1 { err := v1Upgrade(db) diff --git a/indexedDb/impl/state/callbacks.go b/indexedDb/impl/state/callbacks.go new file mode 100644 index 0000000000000000000000000000000000000000..fbeb674ad08e8ab9c6f0ef95fff05e96d178a7d5 --- /dev/null +++ b/indexedDb/impl/state/callbacks.go @@ -0,0 +1,79 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + +//go:build js && wasm + +package main + +import ( + "encoding/json" + "github.com/pkg/errors" + + "gitlab.com/elixxir/client/v4/storage/utility" + stateWorker "gitlab.com/elixxir/xxdk-wasm/indexedDb/worker/state" + "gitlab.com/elixxir/xxdk-wasm/worker" +) + +// manager handles the message callbacks, which is used to +// send information between the model and the main thread. +type manager struct { + wtm *worker.ThreadManager + model utility.WebState +} + +// registerCallbacks registers all the reception callbacks to manage messages +// from the main thread. +func (m *manager) registerCallbacks() { + m.wtm.RegisterCallback(stateWorker.NewStateTag, m.newStateCB) + m.wtm.RegisterCallback(stateWorker.SetTag, m.setCB) + m.wtm.RegisterCallback(stateWorker.GetTag, m.getCB) +} + +// newStateCB is the callback for NewState. Returns an empty +// slice on success or an error message on failure. +func (m *manager) newStateCB(data []byte) ([]byte, error) { + var msg stateWorker.NewStateMessage + err := json.Unmarshal(data, &msg) + if err != nil { + return []byte{}, errors.Errorf( + "failed to JSON unmarshal %T from main thread: %+v", msg, err) + } + + m.model, err = NewState(msg.DatabaseName) + if err != nil { + return []byte(err.Error()), nil + } + + return []byte{}, nil +} + +// setCB is the callback for stateModel.Set. +// Returns nil on error or the resulting byte data on success. +func (m *manager) setCB(data []byte) ([]byte, error) { + var msg stateWorker.TransferMessage + err := json.Unmarshal(data, &msg) + if err != nil { + return nil, errors.Errorf( + "failed to JSON unmarshal %T from main thread: %+v", msg, err) + } + + return nil, m.model.Set(msg.Key, msg.Value) +} + +// getCB is the callback for stateModel.Get. +// Returns nil on error or the resulting byte data on success. +func (m *manager) getCB(data []byte) ([]byte, error) { + key := string(data) + result, err := m.model.Get(key) + msg := stateWorker.TransferMessage{ + Key: key, + Value: result, + Error: err.Error(), + } + + return json.Marshal(msg) +} diff --git a/indexedDb/impl/state/implementation.go b/indexedDb/impl/state/implementation.go new file mode 100644 index 0000000000000000000000000000000000000000..f580eff52c86978782226d9a5adb305d33d0013c --- /dev/null +++ b/indexedDb/impl/state/implementation.go @@ -0,0 +1,66 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + +//go:build js && wasm + +package main + +import ( + "encoding/json" + "github.com/hack-pad/go-indexeddb/idb" + "github.com/pkg/errors" + "gitlab.com/elixxir/wasm-utils/utils" + "gitlab.com/elixxir/xxdk-wasm/indexedDb/impl" + "syscall/js" +) + +// stateModel implements [ClientState] interface backed by IndexedDb. +// NOTE: This model is NOT thread safe - it is the responsibility of the +// caller to ensure that its methods are called sequentially. +type stateModel struct { + db *idb.Database +} + +func (s *stateModel) Get(key string) ([]byte, error) { + result, err := impl.Get(s.db, stateStoreName, js.ValueOf(key)) + if err != nil { + return nil, err + } + + stateObj := &State{} + err = json.Unmarshal([]byte(utils.JsToJson(result)), stateObj) + if err != nil { + return nil, err + } + + return stateObj.Value, err +} + +func (s *stateModel) Set(key string, value []byte) error { + state := &State{ + Id: key, + Value: value, + } + + // Convert to jsObject + newStateJSON, err := json.Marshal(state) + if err != nil { + return errors.Errorf("Unable to marshal State: %+v", err) + } + stateObj, err := utils.JsonToJS(newStateJSON) + if err != nil { + return errors.Errorf("Unable to marshal State: %+v", err) + } + + // Store State to database + _, err = impl.Put(s.db, stateStoreName, stateObj) + if err != nil { + return errors.Errorf("Unable to put State: %+v\n%s", + err, newStateJSON) + } + return nil +} diff --git a/indexedDb/impl/state/init.go b/indexedDb/impl/state/init.go new file mode 100644 index 0000000000000000000000000000000000000000..e5ba9f9add4bd0f55c092a8ddd40ce97d936ebf0 --- /dev/null +++ b/indexedDb/impl/state/init.go @@ -0,0 +1,84 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + +//go:build js && wasm + +package main + +import ( + "github.com/hack-pad/go-indexeddb/idb" + jww "github.com/spf13/jwalterweatherman" + "gitlab.com/elixxir/client/v4/storage/utility" + "gitlab.com/elixxir/xxdk-wasm/indexedDb/impl" + "syscall/js" +) + +// currentVersion is the current version of the IndexedDb runtime. Used for +// migration purposes. +const currentVersion uint = 1 + +// NewState returns a [utility.WebState] backed by IndexedDb. +// The name should be a base64 encoding of the users public key. +func NewState(databaseName string) (utility.WebState, error) { + return newState(databaseName) +} + +// newState creates the given [idb.Database] and returns a stateModel. +func newState(databaseName string) (*stateModel, error) { + // Attempt to open database object + ctx, cancel := impl.NewContext() + defer cancel() + openRequest, err := idb.Global().Open(ctx, databaseName, currentVersion, + func(db *idb.Database, oldVersion, newVersion uint) error { + if oldVersion == newVersion { + jww.INFO.Printf("IndexDb version for %s is current: v%d", + databaseName, newVersion) + return nil + } + + jww.INFO.Printf("IndexDb upgrade required for %s: v%d -> v%d", + databaseName, oldVersion, newVersion) + + if oldVersion == 0 && newVersion >= 1 { + err := v1Upgrade(db) + if err != nil { + return err + } + oldVersion = 1 + } + + // if oldVersion == 1 && newVersion >= 2 { v2Upgrade(), oldVersion = 2 } + return nil + }) + if err != nil { + return nil, err + } + + // Wait for database open to finish + db, err := openRequest.Await(ctx) + if err != nil { + return nil, err + } else if ctx.Err() != nil { + return nil, ctx.Err() + } + + wrapper := &stateModel{db: db} + return wrapper, nil +} + +// v1Upgrade performs the v0 -> v1 database upgrade. +// +// This can never be changed without permanently breaking backwards +// compatibility. +func v1Upgrade(db *idb.Database) error { + storeOpts := idb.ObjectStoreOptions{ + KeyPath: js.ValueOf(pkeyName), + AutoIncrement: false, + } + _, err := db.CreateObjectStore(stateStoreName, storeOpts) + return err +} diff --git a/indexedDb/impl/state/main.go b/indexedDb/impl/state/main.go new file mode 100644 index 0000000000000000000000000000000000000000..719b9969852c2ba946d6365367050878b0dd7b81 --- /dev/null +++ b/indexedDb/impl/state/main.go @@ -0,0 +1,80 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + +//go:build js && wasm + +package main + +import ( + "fmt" + "os" + "syscall/js" + + "github.com/spf13/cobra" + jww "github.com/spf13/jwalterweatherman" + + "gitlab.com/elixxir/xxdk-wasm/logging" + "gitlab.com/elixxir/xxdk-wasm/worker" +) + +// SEMVER is the current semantic version of the xxDK web worker. +const SEMVER = "0.1.0" + +func main() { + // Set to os.Args because the default is os.Args[1:] and in WASM, args start + // at 0, not 1. + channelsCmd.SetArgs(os.Args) + + err := channelsCmd.Execute() + if err != nil { + fmt.Println(err) + os.Exit(1) + } +} + +var channelsCmd = &cobra.Command{ + Use: "stateIndexedDbWorker", + Short: "IndexedDb database for state.", + Example: "const go = new Go();\ngo.argv = [\"--logLevel=1\"]", + Run: func(cmd *cobra.Command, args []string) { + // Start logger first to capture all logging events + err := logging.EnableLogging(logLevel, -1, 0, "", "") + if err != nil { + fmt.Printf("Failed to intialize logging: %+v", err) + os.Exit(1) + } + + jww.INFO.Printf("xxDK state web worker version: v%s", SEMVER) + + jww.INFO.Print("[WW] Starting xxDK WebAssembly State Database Worker.") + m := &manager{ + wtm: worker.NewThreadManager("StateIndexedDbWorker", true), + } + m.registerCallbacks() + m.wtm.SignalReady() + + // Indicate to the Javascript caller that the WASM is ready by resolving + // a promise created by the caller. + js.Global().Get("onWasmInitialized").Invoke() + + <-make(chan bool) + fmt.Println("[WW] Closing xxDK WebAssembly State Database Worker.") + os.Exit(0) + }, +} + +var ( + logLevel jww.Threshold +) + +func init() { + // Initialize all startup flags + channelsCmd.Flags().IntVarP((*int)(&logLevel), "logLevel", "l", 2, + "Sets the log level output when outputting to the Javascript console. "+ + "0 = TRACE, 1 = DEBUG, 2 = INFO, 3 = WARN, 4 = ERROR, "+ + "5 = CRITICAL, 6 = FATAL, -1 = disabled.") +} diff --git a/indexedDb/impl/state/model.go b/indexedDb/impl/state/model.go new file mode 100644 index 0000000000000000000000000000000000000000..5b8638a5ff832cdc028d5dfb7a103faeb9118749 --- /dev/null +++ b/indexedDb/impl/state/model.go @@ -0,0 +1,27 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + +//go:build js && wasm + +package main + +const ( + // Text representation of primary key value (keyPath). + pkeyName = "id" + + // Text representation of the names of the various [idb.ObjectStore]. + stateStoreName = "states" +) + +// State defines the IndexedDb representation of a single KV data store. +type State struct { + // Id is a unique identifier for a given State. + Id string `json:"id"` // Matches pkeyName + + // Value stores the data contents of the State. + Value []byte `json:"value"` +} diff --git a/indexedDb/impl/state/stateIndexedDbWorker.js b/indexedDb/impl/state/stateIndexedDbWorker.js new file mode 100644 index 0000000000000000000000000000000000000000..a7c440d2a862a81737d75418ef39e5464c99ad90 --- /dev/null +++ b/indexedDb/impl/state/stateIndexedDbWorker.js @@ -0,0 +1,21 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + +importScripts('wasm_exec.js'); + +const isReady = new Promise((resolve) => { + self.onWasmInitialized = resolve; +}); + +const go = new Go(); +const binPath = 'xxdk-stateIndexedDkWorker.wasm' +WebAssembly.instantiateStreaming(fetch(binPath), go.importObject).then(async (result) => { + go.run(result.instance); + await isReady; +}).catch((err) => { + console.error(err); +}); \ No newline at end of file diff --git a/indexedDb/worker/state/implementation.go b/indexedDb/worker/state/implementation.go new file mode 100644 index 0000000000000000000000000000000000000000..92a5752ade4aef34f002a3904cc586f047e4c6bb --- /dev/null +++ b/indexedDb/worker/state/implementation.go @@ -0,0 +1,82 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + +//go:build js && wasm + +package dm + +import ( + "encoding/json" + "github.com/pkg/errors" + "time" + + "gitlab.com/elixxir/xxdk-wasm/worker" +) + +type wasmModel struct { + wh *worker.Manager +} + +// TransferMessage is JSON marshalled and sent to the worker. +type TransferMessage struct { + Key string `json:"key"` + Value []byte `json:"value"` + Error string `json:"error"` +} + +func (w *wasmModel) Set(key string, value []byte) error { + msg := TransferMessage{ + Key: key, + Value: value, + } + + data, err := json.Marshal(msg) + if err != nil { + return errors.Errorf( + "Could not JSON marshal payload for TransferMessage: %+v", err) + } + + resultChan := make(chan []byte) + w.wh.SendMessage(SetTag, data, + func(data []byte) { + resultChan <- data + }) + + select { + case result := <-resultChan: + return errors.New(string(result)) + case <-time.After(worker.ResponseTimeout): + return errors.Errorf("Timed out after %s waiting for response from the "+ + "worker about Get", worker.ResponseTimeout) + } +} + +func (w *wasmModel) Get(key string) ([]byte, error) { + resultChan := make(chan []byte) + w.wh.SendMessage(GetTag, []byte(key), + func(data []byte) { + resultChan <- data + }) + + select { + case result := <-resultChan: + var msg TransferMessage + err := json.Unmarshal(result, &msg) + if err != nil { + return nil, errors.Errorf( + "failed to JSON unmarshal %T from main thread: %+v", msg, err) + } + + if len(msg.Error) > 0 { + return nil, errors.New(msg.Error) + } + return msg.Value, nil + case <-time.After(worker.ResponseTimeout): + return nil, errors.Errorf("Timed out after %s waiting for response from the "+ + "worker about Get", worker.ResponseTimeout) + } +} diff --git a/indexedDb/worker/state/init.go b/indexedDb/worker/state/init.go new file mode 100644 index 0000000000000000000000000000000000000000..b4842ae5ca954e1bfead70a483690b88fbf1974d --- /dev/null +++ b/indexedDb/worker/state/init.go @@ -0,0 +1,72 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + +//go:build js && wasm + +package dm + +import ( + "encoding/json" + "time" + + "github.com/pkg/errors" + + "gitlab.com/elixxir/client/v4/storage/utility" + "gitlab.com/elixxir/xxdk-wasm/storage" + "gitlab.com/elixxir/xxdk-wasm/worker" +) + +// databaseSuffix is the suffix to be appended to the name of the database. +const databaseSuffix = "_speakeasy_state" + +// NewStateMessage is JSON marshalled and sent to the worker for +// [NewState]. +type NewStateMessage struct { + DatabaseName string `json:"databaseName"` +} + +// NewState returns a [utility.WebState] backed by indexeddb. +// The name should be a base64 encoding of the users public key. +func NewState(path, wasmJsPath string) (utility.WebState, error) { + databaseName := path + databaseSuffix + + wh, err := worker.NewManager(wasmJsPath, "stateIndexedDb", true) + if err != nil { + return nil, err + } + + // Store the database name + err = storage.StoreIndexedDb(databaseName) + if err != nil { + return nil, err + } + + msg := NewStateMessage{ + DatabaseName: databaseName, + } + + payload, err := json.Marshal(msg) + if err != nil { + return nil, err + } + + dataChan := make(chan []byte) + wh.SendMessage(NewStateTag, payload, + func(data []byte) { dataChan <- data }) + + select { + case data := <-dataChan: + if len(data) > 0 { + return nil, errors.New(string(data)) + } + case <-time.After(worker.ResponseTimeout): + return nil, errors.Errorf("timed out after %s waiting for indexedDB "+ + "database in worker to initialize", worker.ResponseTimeout) + } + + return &wasmModel{wh}, nil +} diff --git a/indexedDb/worker/state/tags.go b/indexedDb/worker/state/tags.go new file mode 100644 index 0000000000000000000000000000000000000000..0f6327d9f54509735fd6e6a1d7de57e3b8015a04 --- /dev/null +++ b/indexedDb/worker/state/tags.go @@ -0,0 +1,20 @@ +//////////////////////////////////////////////////////////////////////////////// +// Copyright © 2022 xx foundation // +// // +// Use of this source code is governed by a license that can be found in the // +// LICENSE file. // +//////////////////////////////////////////////////////////////////////////////// + +//go:build js && wasm + +package dm + +import "gitlab.com/elixxir/xxdk-wasm/worker" + +// List of tags that can be used when sending a message or registering a handler +// to receive a message. +const ( + NewStateTag worker.Tag = "NewState" + SetTag worker.Tag = "Set" + GetTag worker.Tag = "Get" +)