POC showing how statfile can call the conn wshclient to get file info (#242)

This commit is contained in:
Mike Sawka 2024-08-16 18:45:45 -07:00 committed by GitHub
parent e4c74a58bb
commit a451743937
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 44 additions and 24 deletions

View File

@ -26,6 +26,8 @@ import (
"github.com/wavetermdev/thenextwave/pkg/wconfig" "github.com/wavetermdev/thenextwave/pkg/wconfig"
"github.com/wavetermdev/thenextwave/pkg/web" "github.com/wavetermdev/thenextwave/pkg/web"
"github.com/wavetermdev/thenextwave/pkg/wps" "github.com/wavetermdev/thenextwave/pkg/wps"
"github.com/wavetermdev/thenextwave/pkg/wshrpc"
"github.com/wavetermdev/thenextwave/pkg/wshrpc/wshremote"
"github.com/wavetermdev/thenextwave/pkg/wshrpc/wshserver" "github.com/wavetermdev/thenextwave/pkg/wshrpc/wshserver"
"github.com/wavetermdev/thenextwave/pkg/wshutil" "github.com/wavetermdev/thenextwave/pkg/wshutil"
"github.com/wavetermdev/thenextwave/pkg/wstore" "github.com/wavetermdev/thenextwave/pkg/wstore"
@ -152,6 +154,8 @@ func createMainWshClient() {
rpc := wshserver.GetMainRpcClient() rpc := wshserver.GetMainRpcClient()
wshutil.DefaultRouter.RegisterRoute(wshutil.DefaultRoute, rpc) wshutil.DefaultRouter.RegisterRoute(wshutil.DefaultRoute, rpc)
wps.Broker.SetClient(wshutil.DefaultRouter) wps.Broker.SetClient(wshutil.DefaultRouter)
localConnWsh := wshutil.MakeWshRpc(nil, nil, wshrpc.RpcContext{}, &wshremote.ServerImpl{})
wshutil.DefaultRouter.RegisterRoute(wshutil.MakeConnectionRouteId(wshrpc.LocalConnName), localConnWsh)
} }
func main() { func main() {

View File

@ -74,7 +74,9 @@ class FileServiceType {
SaveFile(arg1: string, arg2: string): Promise<void> { SaveFile(arg1: string, arg2: string): Promise<void> {
return WOS.callBackendService("file", "SaveFile", Array.from(arguments)) return WOS.callBackendService("file", "SaveFile", Array.from(arguments))
} }
StatFile(arg1: string): Promise<FileInfo> {
// get file info
StatFile(connection: string, path: string): Promise<FileInfo> {
return WOS.callBackendService("file", "StatFile", Array.from(arguments)) return WOS.callBackendService("file", "StatFile", Array.from(arguments))
} }
} }

View File

@ -44,6 +44,7 @@ export class PreviewModel implements ViewModel {
isCeView: jotai.PrimitiveAtom<boolean>; isCeView: jotai.PrimitiveAtom<boolean>;
fileName: jotai.WritableAtom<string, [string], void>; fileName: jotai.WritableAtom<string, [string], void>;
connection: jotai.Atom<string>;
statFile: jotai.Atom<Promise<FileInfo>>; statFile: jotai.Atom<Promise<FileInfo>>;
fullFile: jotai.Atom<Promise<FullFile>>; fullFile: jotai.Atom<Promise<FullFile>>;
fileMimeType: jotai.Atom<Promise<string>>; fileMimeType: jotai.Atom<Promise<string>>;
@ -187,7 +188,6 @@ export class PreviewModel implements ViewModel {
} }
return null; return null;
}); });
this.fileName = jotai.atom<string, [string], void>( this.fileName = jotai.atom<string, [string], void>(
(get) => { (get) => {
return get(this.blockAtom)?.meta?.file; return get(this.blockAtom)?.meta?.file;
@ -196,14 +196,18 @@ export class PreviewModel implements ViewModel {
services.ObjectService.UpdateObjectMeta(`block:${blockId}`, { file: update }); services.ObjectService.UpdateObjectMeta(`block:${blockId}`, { file: update });
} }
); );
this.connection = jotai.atom<string>((get) => {
return get(this.blockAtom)?.meta?.connection;
});
this.statFile = jotai.atom<Promise<FileInfo>>(async (get) => { this.statFile = jotai.atom<Promise<FileInfo>>(async (get) => {
const fileName = get(this.fileName); const fileName = get(this.fileName);
if (fileName == null) { if (fileName == null) {
return null; return null;
} }
const conn = get(this.connection) ?? "";
// const statFile = await FileService.StatFile(fileName); // const statFile = await FileService.StatFile(fileName);
console.log("PreviewModel calling StatFile", fileName); console.log("PreviewModel calling StatFile", conn, fileName);
const statFile = await services.FileService.StatFile(fileName); const statFile = await services.FileService.StatFile(conn, fileName);
return statFile; return statFile;
}); });
this.fullFile = jotai.atom<Promise<FullFile>>(async (get) => { this.fullFile = jotai.atom<Promise<FullFile>>(async (get) => {

View File

@ -11,10 +11,14 @@ import (
"time" "time"
"github.com/wavetermdev/thenextwave/pkg/filestore" "github.com/wavetermdev/thenextwave/pkg/filestore"
"github.com/wavetermdev/thenextwave/pkg/tsgen/tsgenmeta"
"github.com/wavetermdev/thenextwave/pkg/util/utilfn" "github.com/wavetermdev/thenextwave/pkg/util/utilfn"
"github.com/wavetermdev/thenextwave/pkg/wavebase" "github.com/wavetermdev/thenextwave/pkg/wavebase"
"github.com/wavetermdev/thenextwave/pkg/wconfig" "github.com/wavetermdev/thenextwave/pkg/wconfig"
"github.com/wavetermdev/thenextwave/pkg/wshrpc" "github.com/wavetermdev/thenextwave/pkg/wshrpc"
"github.com/wavetermdev/thenextwave/pkg/wshrpc/wshclient"
"github.com/wavetermdev/thenextwave/pkg/wshrpc/wshserver"
"github.com/wavetermdev/thenextwave/pkg/wshutil"
) )
const MaxFileSize = 10 * 1024 * 1024 // 10M const MaxFileSize = 10 * 1024 * 1024 // 10M
@ -40,30 +44,24 @@ func (fs *FileService) SaveFile(path string, data64 string) error {
return nil return nil
} }
func (fs *FileService) StatFile(path string) (*wshrpc.FileInfo, error) { func (fs *FileService) StatFile_Meta() tsgenmeta.MethodMeta {
cleanedPath := filepath.Clean(wavebase.ExpandHomeDir(path)) return tsgenmeta.MethodMeta{
finfo, err := os.Stat(cleanedPath) Desc: "get file info",
if os.IsNotExist(err) { ArgNames: []string{"connection", "path"},
return &wshrpc.FileInfo{Path: wavebase.ReplaceHomeDir(path), NotFound: true}, nil
} }
if err != nil { }
return nil, fmt.Errorf("cannot stat file %q: %w", path, err)
func (fs *FileService) StatFile(connection string, path string) (*wshrpc.FileInfo, error) {
if connection == "" {
connection = wshrpc.LocalConnName
} }
mimeType := utilfn.DetectMimeType(cleanedPath) connRoute := wshutil.MakeConnectionRouteId(connection)
return &wshrpc.FileInfo{ client := wshserver.GetMainRpcClient()
Path: cleanedPath, return wshclient.RemoteFileInfoCommand(client, path, &wshrpc.RpcOpts{Route: connRoute})
Name: finfo.Name(),
Size: finfo.Size(),
Mode: finfo.Mode(),
ModeStr: finfo.Mode().String(),
ModTime: finfo.ModTime().UnixMilli(),
IsDir: finfo.IsDir(),
MimeType: mimeType,
}, nil
} }
func (fs *FileService) ReadFile(path string) (*FullFile, error) { func (fs *FileService) ReadFile(path string) (*FullFile, error) {
finfo, err := fs.StatFile(path) finfo, err := fs.StatFile("", path)
if err != nil { if err != nil {
return nil, fmt.Errorf("cannot stat file %q: %w", path, err) return nil, fmt.Errorf("cannot stat file %q: %w", path, err)
} }
@ -83,7 +81,7 @@ func (fs *FileService) ReadFile(path string) (*FullFile, error) {
} }
var innerFilesInfo []wshrpc.FileInfo var innerFilesInfo []wshrpc.FileInfo
parent := filepath.Dir(finfo.Path) parent := filepath.Dir(finfo.Path)
parentFileInfo, err := fs.StatFile(parent) parentFileInfo, err := fs.StatFile("", parent)
if err == nil && parent != finfo.Path { if err == nil && parent != finfo.Path {
log.Printf("adding parent") log.Printf("adding parent")
parentFileInfo.Name = ".." parentFileInfo.Name = ".."

View File

@ -16,6 +16,8 @@ import (
"github.com/wavetermdev/thenextwave/pkg/wstore" "github.com/wavetermdev/thenextwave/pkg/wstore"
) )
const LocalConnName = "local"
const ( const (
RpcType_Call = "call" // single response (regular rpc) RpcType_Call = "call" // single response (regular rpc)
RpcType_ResponseStream = "responsestream" // stream of responses (streaming rpc) RpcType_ResponseStream = "responsestream" // stream of responses (streaming rpc)

View File

@ -38,6 +38,10 @@ type WshRouter struct {
InputCh chan msgAndRoute InputCh chan msgAndRoute
} }
func MakeConnectionRouteId(connId string) string {
return "conn:" + connId
}
var DefaultRouter = NewWshRouter() var DefaultRouter = NewWshRouter()
func NewWshRouter() *WshRouter { func NewWshRouter() *WshRouter {

View File

@ -180,6 +180,12 @@ func validateServerImpl(serverImpl ServerImpl) {
// closes outputCh when inputCh is closed/done // closes outputCh when inputCh is closed/done
func MakeWshRpc(inputCh chan []byte, outputCh chan []byte, rpcCtx wshrpc.RpcContext, serverImpl ServerImpl) *WshRpc { func MakeWshRpc(inputCh chan []byte, outputCh chan []byte, rpcCtx wshrpc.RpcContext, serverImpl ServerImpl) *WshRpc {
if inputCh == nil {
inputCh = make(chan []byte, DefaultInputChSize)
}
if outputCh == nil {
outputCh = make(chan []byte, DefaultOutputChSize)
}
validateServerImpl(serverImpl) validateServerImpl(serverImpl)
rtn := &WshRpc{ rtn := &WshRpc{
Lock: &sync.Mutex{}, Lock: &sync.Mutex{},