mirror of
https://github.com/wavetermdev/waveterm.git
synced 2024-12-21 16:38:23 +01:00
checkpoint on new objectservice
This commit is contained in:
parent
b1aaba2a37
commit
95ce1cc86d
26
cmd/generate/main-generate.go
Normal file
26
cmd/generate/main-generate.go
Normal file
@ -0,0 +1,26 @@
|
||||
// Copyright 2024, Command Line Inc.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"github.com/wavetermdev/thenextwave/pkg/waveobj"
|
||||
"github.com/wavetermdev/thenextwave/pkg/wstore"
|
||||
)
|
||||
|
||||
func main() {
|
||||
tsTypesMap := make(map[reflect.Type]string)
|
||||
var waveObj waveobj.WaveObj
|
||||
waveobj.GenerateTSType(reflect.TypeOf(waveobj.ORef{}), tsTypesMap)
|
||||
waveobj.GenerateTSType(reflect.TypeOf(&waveObj).Elem(), tsTypesMap)
|
||||
for _, rtype := range wstore.AllWaveObjTypes() {
|
||||
waveobj.GenerateTSType(rtype, tsTypesMap)
|
||||
}
|
||||
for _, ts := range tsTypesMap {
|
||||
fmt.Print(ts)
|
||||
fmt.Print("\n")
|
||||
}
|
||||
}
|
@ -1,15 +1,18 @@
|
||||
// Copyright 2024, Command Line Inc.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import * as React from "react";
|
||||
import * as jotai from "jotai";
|
||||
import { atomFamily } from "jotai/utils";
|
||||
import * as jotaiUtils from "jotai/utils";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import * as rxjs from "rxjs";
|
||||
import type { WailsEvent } from "@wailsio/runtime/types/events";
|
||||
import { Events } from "@wailsio/runtime";
|
||||
import { produce } from "immer";
|
||||
import { BlockService } from "@/bindings/blockservice";
|
||||
import { ObjectService } from "@/bindings/objectservice";
|
||||
import * as wstore from "@/gopkg/wstore";
|
||||
import { Call as $Call } from "@wailsio/runtime";
|
||||
|
||||
const globalStore = jotai.createStore();
|
||||
|
||||
@ -105,4 +108,93 @@ function removeBlockFromTab(tabId: string, blockId: string) {
|
||||
BlockService.CloseBlock(blockId);
|
||||
}
|
||||
|
||||
export { globalStore, atoms, getBlockSubject, addBlockIdToTab, blockDataMap, useBlockAtom, removeBlockFromTab };
|
||||
function GetObject(oref: string): Promise<any> {
|
||||
let prtn = $Call.ByName(
|
||||
"github.com/wavetermdev/thenextwave/pkg/service/objectservice.ObjectService.GetObject",
|
||||
oref
|
||||
);
|
||||
return prtn;
|
||||
}
|
||||
|
||||
type WaveObjectHookData = {
|
||||
oref: string;
|
||||
};
|
||||
|
||||
type WaveObjectValue<T> = {
|
||||
pendingPromise: Promise<any>;
|
||||
value: T;
|
||||
loading: boolean;
|
||||
};
|
||||
|
||||
const waveObjectValueCache = new Map<string, WaveObjectValue<any>>();
|
||||
let waveObjectAtomCache = new WeakMap<WaveObjectHookData, jotai.Atom<any>>();
|
||||
|
||||
function clearWaveObjectCache() {
|
||||
waveObjectValueCache.clear();
|
||||
waveObjectAtomCache = new WeakMap<WaveObjectHookData, jotai.Atom<any>>();
|
||||
}
|
||||
|
||||
function createWaveObjectAtom<T>(oref: string): jotai.Atom<[T, boolean]> {
|
||||
let cacheVal: WaveObjectValue<T> = waveObjectValueCache.get(oref);
|
||||
if (cacheVal == null) {
|
||||
cacheVal = { pendingPromise: null, value: null, loading: true };
|
||||
cacheVal.pendingPromise = GetObject(oref).then((val) => {
|
||||
cacheVal.value = val;
|
||||
cacheVal.loading = false;
|
||||
cacheVal.pendingPromise = null;
|
||||
});
|
||||
waveObjectValueCache.set(oref, cacheVal);
|
||||
}
|
||||
return jotai.atom(
|
||||
(get) => {
|
||||
return [cacheVal.value, cacheVal.loading];
|
||||
},
|
||||
(get, set, newVal: T) => {
|
||||
cacheVal.value = newVal;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function useWaveObjectValue<T>(oref: string): [T, boolean] {
|
||||
const objRef = React.useRef<WaveObjectHookData>(null);
|
||||
if (objRef.current == null) {
|
||||
objRef.current = { oref: oref };
|
||||
}
|
||||
const objHookData = objRef.current;
|
||||
let objAtom = waveObjectAtomCache.get(objHookData);
|
||||
if (objAtom == null) {
|
||||
objAtom = createWaveObjectAtom(oref);
|
||||
waveObjectAtomCache.set(objHookData, objAtom);
|
||||
}
|
||||
const atomVal = jotai.useAtomValue(objAtom);
|
||||
return [atomVal[0], atomVal[1]];
|
||||
}
|
||||
|
||||
function useWaveObject<T>(oref: string): [T, boolean, (T) => void] {
|
||||
const objRef = React.useRef<WaveObjectHookData>(null);
|
||||
if (objRef.current == null) {
|
||||
objRef.current = { oref: oref };
|
||||
}
|
||||
const objHookData = objRef.current;
|
||||
let objAtom = waveObjectAtomCache.get(objHookData);
|
||||
if (objAtom == null) {
|
||||
objAtom = createWaveObjectAtom(oref);
|
||||
waveObjectAtomCache.set(objHookData, objAtom);
|
||||
}
|
||||
const [atomVal, setAtomVal] = jotai.useAtom(objAtom);
|
||||
return [atomVal[0], atomVal[1], setAtomVal];
|
||||
}
|
||||
|
||||
export {
|
||||
globalStore,
|
||||
atoms,
|
||||
getBlockSubject,
|
||||
addBlockIdToTab,
|
||||
blockDataMap,
|
||||
useBlockAtom,
|
||||
removeBlockFromTab,
|
||||
GetObject,
|
||||
useWaveObject,
|
||||
useWaveObjectValue,
|
||||
clearWaveObjectCache,
|
||||
};
|
||||
|
93
frontend/types/custom.d.ts
vendored
93
frontend/types/custom.d.ts
vendored
@ -1,6 +1,97 @@
|
||||
// Copyright 2024, Command Line Inc.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
declare global {}
|
||||
declare global {
|
||||
type ORef = {
|
||||
otype: string;
|
||||
oid: string;
|
||||
};
|
||||
|
||||
type Block = {
|
||||
otype: string;
|
||||
oid: string;
|
||||
version: number;
|
||||
blockdef: BlockDef;
|
||||
controller: string;
|
||||
view: string;
|
||||
meta?: { [key: string]: any };
|
||||
runtimeopts?: RuntimeOpts;
|
||||
};
|
||||
|
||||
type BlockDef = {
|
||||
controller: string;
|
||||
view?: string;
|
||||
files?: { [key: string]: FileDef };
|
||||
meta?: { [key: string]: any };
|
||||
};
|
||||
|
||||
type FileDef = {
|
||||
filetype?: string;
|
||||
path?: string;
|
||||
url?: string;
|
||||
content?: string;
|
||||
meta?: { [key: string]: any };
|
||||
};
|
||||
|
||||
type TermSize = {
|
||||
rows: number;
|
||||
cols: number;
|
||||
};
|
||||
|
||||
type Client = {
|
||||
otype: string;
|
||||
oid: string;
|
||||
version: number;
|
||||
mainwindowid: string;
|
||||
};
|
||||
|
||||
type Tab = {
|
||||
otype: string;
|
||||
oid: string;
|
||||
version: number;
|
||||
name: string;
|
||||
blockids: string[];
|
||||
};
|
||||
|
||||
type Point = {
|
||||
x: number;
|
||||
y: number;
|
||||
};
|
||||
|
||||
type WinSize = {
|
||||
width: number;
|
||||
height: number;
|
||||
};
|
||||
|
||||
type Workspace = {
|
||||
otype: string;
|
||||
oid: string;
|
||||
version: number;
|
||||
name: string;
|
||||
tabids: string[];
|
||||
};
|
||||
|
||||
type RuntimeOpts = {
|
||||
termsize?: TermSize;
|
||||
winsize?: WinSize;
|
||||
};
|
||||
|
||||
type WaveObj = {
|
||||
otype: string;
|
||||
oid: string;
|
||||
};
|
||||
|
||||
type Window = {
|
||||
otype: string;
|
||||
oid: string;
|
||||
version: number;
|
||||
workspaceid: string;
|
||||
activetabid: string;
|
||||
activeblockmap: { [key: string]: string };
|
||||
pos: Point;
|
||||
winsize: WinSize;
|
||||
lastfocusts: number;
|
||||
};
|
||||
}
|
||||
|
||||
export {};
|
||||
|
2
main.go
2
main.go
@ -19,6 +19,7 @@ import (
|
||||
"github.com/wavetermdev/thenextwave/pkg/service/blockservice"
|
||||
"github.com/wavetermdev/thenextwave/pkg/service/clientservice"
|
||||
"github.com/wavetermdev/thenextwave/pkg/service/fileservice"
|
||||
"github.com/wavetermdev/thenextwave/pkg/service/objectservice"
|
||||
"github.com/wavetermdev/thenextwave/pkg/wavebase"
|
||||
"github.com/wavetermdev/thenextwave/pkg/wstore"
|
||||
|
||||
@ -131,6 +132,7 @@ func main() {
|
||||
application.NewService(&fileservice.FileService{}),
|
||||
application.NewService(&blockservice.BlockService{}),
|
||||
application.NewService(&clientservice.ClientService{}),
|
||||
application.NewService(&objectservice.ObjectService{}),
|
||||
},
|
||||
Icon: appIcon,
|
||||
Assets: application.AssetOptions{
|
||||
|
55
pkg/service/objectservice/objectservice.go
Normal file
55
pkg/service/objectservice/objectservice.go
Normal file
@ -0,0 +1,55 @@
|
||||
// Copyright 2024, Command Line Inc.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package objectservice
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/wavetermdev/thenextwave/pkg/waveobj"
|
||||
"github.com/wavetermdev/thenextwave/pkg/wstore"
|
||||
)
|
||||
|
||||
type ObjectService struct{}
|
||||
|
||||
const DefaultTimeout = 2 * time.Second
|
||||
|
||||
func parseORef(oref string) (*waveobj.ORef, error) {
|
||||
fields := strings.Split(oref, ":")
|
||||
if len(fields) != 2 {
|
||||
return nil, fmt.Errorf("invalid object reference: %q", oref)
|
||||
}
|
||||
return &waveobj.ORef{OType: fields[0], OID: fields[1]}, nil
|
||||
}
|
||||
|
||||
func (svc *ObjectService) GetObject(orefStr string) (any, error) {
|
||||
oref, err := parseORef(orefStr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ctx, cancelFn := context.WithTimeout(context.Background(), DefaultTimeout)
|
||||
defer cancelFn()
|
||||
obj, err := wstore.DBGetORef(ctx, *oref)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error getting object: %w", err)
|
||||
}
|
||||
return obj, nil
|
||||
}
|
||||
|
||||
func (svc *ObjectService) GetObjects(orefStrArr []string) (any, error) {
|
||||
ctx, cancelFn := context.WithTimeout(context.Background(), DefaultTimeout)
|
||||
defer cancelFn()
|
||||
|
||||
var orefArr []waveobj.ORef
|
||||
for _, orefStr := range orefStrArr {
|
||||
orefObj, err := parseORef(orefStr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
orefArr = append(orefArr, *orefObj)
|
||||
}
|
||||
return wstore.DBSelectORefs(ctx, orefArr)
|
||||
}
|
@ -23,6 +23,11 @@ const (
|
||||
VersionGoFieldName = "Version"
|
||||
)
|
||||
|
||||
type ORef struct {
|
||||
OType string `json:"otype"`
|
||||
OID string `json:"oid"`
|
||||
}
|
||||
|
||||
type WaveObj interface {
|
||||
GetOType() string // should not depend on object state (should work with nil value)
|
||||
}
|
||||
@ -36,35 +41,37 @@ type waveObjDesc struct {
|
||||
var waveObjMap = sync.Map{}
|
||||
var waveObjRType = reflect.TypeOf((*WaveObj)(nil)).Elem()
|
||||
|
||||
func RegisterType[T WaveObj]() {
|
||||
var waveObj T
|
||||
func RegisterType(rtype reflect.Type) {
|
||||
if rtype.Kind() != reflect.Ptr {
|
||||
panic(fmt.Sprintf("wave object must be a pointer for %v", rtype))
|
||||
}
|
||||
if !rtype.Implements(waveObjRType) {
|
||||
panic(fmt.Sprintf("wave object must implement WaveObj for %v", rtype))
|
||||
}
|
||||
waveObj := reflect.Zero(rtype).Interface().(WaveObj)
|
||||
otype := waveObj.GetOType()
|
||||
if otype == "" {
|
||||
panic(fmt.Sprintf("otype is empty for %T", waveObj))
|
||||
}
|
||||
rtype := reflect.TypeOf(waveObj)
|
||||
if rtype.Kind() != reflect.Ptr {
|
||||
panic(fmt.Sprintf("wave object must be a pointer for %T", waveObj))
|
||||
panic(fmt.Sprintf("otype is empty for %v", rtype))
|
||||
}
|
||||
oidField, found := rtype.Elem().FieldByName(OIDGoFieldName)
|
||||
if !found {
|
||||
panic(fmt.Sprintf("missing OID field for %T", waveObj))
|
||||
panic(fmt.Sprintf("missing OID field for %v", rtype))
|
||||
}
|
||||
if oidField.Type.Kind() != reflect.String {
|
||||
panic(fmt.Sprintf("OID field must be string for %T", waveObj))
|
||||
panic(fmt.Sprintf("OID field must be string for %v", rtype))
|
||||
}
|
||||
if oidField.Tag.Get("json") != OIDKeyName {
|
||||
panic(fmt.Sprintf("OID field json tag must be %q for %T", OIDKeyName, waveObj))
|
||||
panic(fmt.Sprintf("OID field json tag must be %q for %v", OIDKeyName, rtype))
|
||||
}
|
||||
versionField, found := rtype.Elem().FieldByName(VersionGoFieldName)
|
||||
if !found {
|
||||
panic(fmt.Sprintf("missing Version field for %T", waveObj))
|
||||
panic(fmt.Sprintf("missing Version field for %v", rtype))
|
||||
}
|
||||
if versionField.Type.Kind() != reflect.Int {
|
||||
panic(fmt.Sprintf("Version field must be int for %T", waveObj))
|
||||
panic(fmt.Sprintf("Version field must be int for %v", rtype))
|
||||
}
|
||||
if versionField.Tag.Get("json") != VersionKeyName {
|
||||
panic(fmt.Sprintf("Version field json tag must be %q for %T", VersionKeyName, waveObj))
|
||||
panic(fmt.Sprintf("Version field json tag must be %q for %v", VersionKeyName, rtype))
|
||||
}
|
||||
_, found = waveObjMap.Load(otype)
|
||||
if found {
|
||||
@ -286,16 +293,16 @@ func generateTSTypeInternal(rtype reflect.Type) (string, []reflect.Type) {
|
||||
subTypes = append(subTypes, fieldSubTypes...)
|
||||
buf.WriteString(fmt.Sprintf(" %s%s: %s;\n", fieldName, optMarker, tsType))
|
||||
}
|
||||
buf.WriteString("}\n")
|
||||
buf.WriteString("};\n")
|
||||
return buf.String(), subTypes
|
||||
}
|
||||
|
||||
func GenerateWaveObjTSType() string {
|
||||
var buf bytes.Buffer
|
||||
buf.WriteString("type WaveObj {\n")
|
||||
buf.WriteString("type WaveObj = {\n")
|
||||
buf.WriteString(" otype: string;\n")
|
||||
buf.WriteString(" oid: string;\n")
|
||||
buf.WriteString("}\n")
|
||||
buf.WriteString("};\n")
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,7 @@ package wstore
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
@ -19,11 +20,9 @@ var TabMap = ds.NewSyncMap[*Tab]()
|
||||
var BlockMap = ds.NewSyncMap[*Block]()
|
||||
|
||||
func init() {
|
||||
waveobj.RegisterType[*Client]()
|
||||
waveobj.RegisterType[*Window]()
|
||||
waveobj.RegisterType[*Workspace]()
|
||||
waveobj.RegisterType[*Tab]()
|
||||
waveobj.RegisterType[*Block]()
|
||||
for _, rtype := range AllWaveObjTypes() {
|
||||
waveobj.RegisterType(rtype)
|
||||
}
|
||||
}
|
||||
|
||||
type Client struct {
|
||||
@ -36,6 +35,16 @@ func (*Client) GetOType() string {
|
||||
return "client"
|
||||
}
|
||||
|
||||
func AllWaveObjTypes() []reflect.Type {
|
||||
return []reflect.Type{
|
||||
reflect.TypeOf(&Client{}),
|
||||
reflect.TypeOf(&Window{}),
|
||||
reflect.TypeOf(&Workspace{}),
|
||||
reflect.TypeOf(&Tab{}),
|
||||
reflect.TypeOf(&Block{}),
|
||||
}
|
||||
}
|
||||
|
||||
// stores the ui-context of the window
|
||||
// workspaceid, active tab, active block within each tab, window size, etc.
|
||||
type Window struct {
|
||||
@ -147,6 +156,10 @@ func CreateWorkspace() (*Workspace, error) {
|
||||
return ws, nil
|
||||
}
|
||||
|
||||
func GetObject(otype string, oid string) (waveobj.WaveObj, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func EnsureInitialData() error {
|
||||
ctx, cancelFn := context.WithTimeout(context.Background(), 2*time.Second)
|
||||
defer cancelFn()
|
||||
|
@ -14,9 +14,18 @@ func waveObjTableName(w waveobj.WaveObj) string {
|
||||
return "db_" + w.GetOType()
|
||||
}
|
||||
|
||||
func tableNameFromOType(otype string) string {
|
||||
return "db_" + otype
|
||||
}
|
||||
|
||||
func tableNameGen[T waveobj.WaveObj]() string {
|
||||
var zeroObj T
|
||||
return "db_" + zeroObj.GetOType()
|
||||
return tableNameFromOType(zeroObj.GetOType())
|
||||
}
|
||||
|
||||
func getOTypeGen[T waveobj.WaveObj]() string {
|
||||
var zeroObj T
|
||||
return zeroObj.GetOType()
|
||||
}
|
||||
|
||||
func DBGetCount[T waveobj.WaveObj](ctx context.Context) (int, error) {
|
||||
@ -33,13 +42,26 @@ type idDataType struct {
|
||||
Data []byte
|
||||
}
|
||||
|
||||
func genericCastWithErr[T any](v any, err error) (T, error) {
|
||||
if err != nil {
|
||||
var zeroVal T
|
||||
return zeroVal, err
|
||||
}
|
||||
return v.(T), err
|
||||
}
|
||||
|
||||
func DBGetSingleton[T waveobj.WaveObj](ctx context.Context) (T, error) {
|
||||
return WithTxRtn(ctx, func(tx *TxWrap) (T, error) {
|
||||
table := tableNameGen[T]()
|
||||
rtn, err := DBGetSingletonByType(ctx, getOTypeGen[T]())
|
||||
return genericCastWithErr[T](rtn, err)
|
||||
}
|
||||
|
||||
func DBGetSingletonByType(ctx context.Context, otype string) (waveobj.WaveObj, error) {
|
||||
return WithTxRtn(ctx, func(tx *TxWrap) (waveobj.WaveObj, error) {
|
||||
table := tableNameFromOType(otype)
|
||||
query := fmt.Sprintf("SELECT oid, version, data FROM %s LIMIT 1", table)
|
||||
var row idDataType
|
||||
tx.Get(&row, query)
|
||||
rtn, err := waveobj.FromJsonGen[T](row.Data)
|
||||
rtn, err := waveobj.FromJson(row.Data)
|
||||
if err != nil {
|
||||
return rtn, err
|
||||
}
|
||||
@ -49,12 +71,17 @@ func DBGetSingleton[T waveobj.WaveObj](ctx context.Context) (T, error) {
|
||||
}
|
||||
|
||||
func DBGet[T waveobj.WaveObj](ctx context.Context, id string) (T, error) {
|
||||
return WithTxRtn(ctx, func(tx *TxWrap) (T, error) {
|
||||
table := tableNameGen[T]()
|
||||
rtn, err := DBGetORef(ctx, waveobj.ORef{OType: getOTypeGen[T](), OID: id})
|
||||
return genericCastWithErr[T](rtn, err)
|
||||
}
|
||||
|
||||
func DBGetORef(ctx context.Context, oref waveobj.ORef) (waveobj.WaveObj, error) {
|
||||
return WithTxRtn(ctx, func(tx *TxWrap) (waveobj.WaveObj, error) {
|
||||
table := tableNameFromOType(oref.OType)
|
||||
query := fmt.Sprintf("SELECT oid, version, data FROM %s WHERE oid = ?", table)
|
||||
var row idDataType
|
||||
tx.Get(&row, query, id)
|
||||
rtn, err := waveobj.FromJsonGen[T](row.Data)
|
||||
tx.Get(&row, query, oref.OID)
|
||||
rtn, err := waveobj.FromJson(row.Data)
|
||||
if err != nil {
|
||||
return rtn, err
|
||||
}
|
||||
@ -63,31 +90,58 @@ func DBGet[T waveobj.WaveObj](ctx context.Context, id string) (T, error) {
|
||||
})
|
||||
}
|
||||
|
||||
func DBSelectMap[T waveobj.WaveObj](ctx context.Context, ids []string) (map[string]T, error) {
|
||||
return WithTxRtn(ctx, func(tx *TxWrap) (map[string]T, error) {
|
||||
table := tableNameGen[T]()
|
||||
var rows []idDataType
|
||||
func dbSelectOIDs(ctx context.Context, otype string, oids []string) ([]waveobj.WaveObj, error) {
|
||||
return WithTxRtn(ctx, func(tx *TxWrap) ([]waveobj.WaveObj, error) {
|
||||
table := tableNameFromOType(otype)
|
||||
query := fmt.Sprintf("SELECT oid, version, data FROM %s WHERE oid IN (SELECT value FROM json_each(?))", table)
|
||||
tx.Select(&rows, query, ids)
|
||||
rtnMap := make(map[string]T)
|
||||
var rows []idDataType
|
||||
tx.Select(&rows, query, oids)
|
||||
rtn := make([]waveobj.WaveObj, 0, len(rows))
|
||||
for _, row := range rows {
|
||||
if row.OId == "" || len(row.Data) == 0 {
|
||||
continue
|
||||
}
|
||||
waveObj, err := waveobj.FromJsonGen[T](row.Data)
|
||||
waveObj, err := waveobj.FromJson(row.Data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
waveobj.SetVersion(waveObj, row.Version)
|
||||
rtnMap[row.OId] = waveObj
|
||||
rtn = append(rtn, waveObj)
|
||||
}
|
||||
return rtnMap, nil
|
||||
return rtn, nil
|
||||
})
|
||||
}
|
||||
|
||||
func DBDelete[T waveobj.WaveObj](ctx context.Context, id string) error {
|
||||
func DBSelectORefs(ctx context.Context, orefs []waveobj.ORef) ([]waveobj.WaveObj, error) {
|
||||
oidsByType := make(map[string][]string)
|
||||
for _, oref := range orefs {
|
||||
oidsByType[oref.OType] = append(oidsByType[oref.OType], oref.OID)
|
||||
}
|
||||
return WithTxRtn(ctx, func(tx *TxWrap) ([]waveobj.WaveObj, error) {
|
||||
rtn := make([]waveobj.WaveObj, 0, len(orefs))
|
||||
for otype, oids := range oidsByType {
|
||||
rtnArr, err := dbSelectOIDs(tx.Context(), otype, oids)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rtn = append(rtn, rtnArr...)
|
||||
}
|
||||
return rtn, nil
|
||||
})
|
||||
}
|
||||
|
||||
func DBSelectMap[T waveobj.WaveObj](ctx context.Context, ids []string) (map[string]T, error) {
|
||||
rtnArr, err := dbSelectOIDs(ctx, getOTypeGen[T](), ids)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rtnMap := make(map[string]T)
|
||||
for _, obj := range rtnArr {
|
||||
rtnMap[waveobj.GetOID(obj)] = obj.(T)
|
||||
}
|
||||
return rtnMap, nil
|
||||
}
|
||||
|
||||
func DBDelete(ctx context.Context, otype string, id string) error {
|
||||
return WithTx(ctx, func(tx *TxWrap) error {
|
||||
table := tableNameGen[T]()
|
||||
table := tableNameFromOType(otype)
|
||||
query := fmt.Sprintf("DELETE FROM %s WHERE oid = ?", table)
|
||||
tx.Exec(query, id)
|
||||
return nil
|
||||
@ -111,7 +165,7 @@ func DBUpdate(ctx context.Context, val waveobj.WaveObj) error {
|
||||
})
|
||||
}
|
||||
|
||||
func DBInsert[T waveobj.WaveObj](ctx context.Context, val T) error {
|
||||
func DBInsert(ctx context.Context, val waveobj.WaveObj) error {
|
||||
oid := waveobj.GetOID(val)
|
||||
if oid == "" {
|
||||
return fmt.Errorf("cannot insert %T value with empty id", val)
|
||||
|
Loading…
Reference in New Issue
Block a user