2024-03-22 18:05:47 +08:00
|
|
|
package xfile
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bufio"
|
2025-02-07 18:00:10 +08:00
|
|
|
"context"
|
2024-03-22 18:05:47 +08:00
|
|
|
"encoding/json"
|
2025-02-05 18:07:53 +08:00
|
|
|
"fmt"
|
2025-02-07 18:00:10 +08:00
|
|
|
"io"
|
2024-03-22 18:05:47 +08:00
|
|
|
"os"
|
2024-03-26 17:23:10 +08:00
|
|
|
|
2024-12-13 15:01:40 +08:00
|
|
|
"github.com/loveuer/esgo2dump/internal/opt"
|
2025-02-05 18:07:53 +08:00
|
|
|
"github.com/loveuer/esgo2dump/pkg/log"
|
|
|
|
"github.com/loveuer/esgo2dump/pkg/model"
|
2024-03-22 18:05:47 +08:00
|
|
|
)
|
|
|
|
|
|
|
|
type client struct {
|
2025-02-05 18:07:53 +08:00
|
|
|
info os.FileInfo
|
2024-03-22 18:05:47 +08:00
|
|
|
f *os.File
|
|
|
|
scanner *bufio.Scanner
|
|
|
|
}
|
|
|
|
|
2025-02-07 18:00:10 +08:00
|
|
|
func (c *client) ReadData(ctx context.Context, limit int, query map[string]any, fields []string, sort []string) ([]map[string]any, error) {
|
2025-02-05 18:07:53 +08:00
|
|
|
if len(query) != 0 {
|
|
|
|
return nil, fmt.Errorf("file with query is unsupported")
|
2024-05-24 17:27:52 +08:00
|
|
|
}
|
|
|
|
|
2025-02-05 18:07:53 +08:00
|
|
|
if len(sort) != 0 {
|
|
|
|
return nil, fmt.Errorf("file with sort is unsupported")
|
2024-03-22 18:05:47 +08:00
|
|
|
}
|
|
|
|
|
2025-02-05 18:07:53 +08:00
|
|
|
list := make([]map[string]any, 0, limit)
|
2024-03-22 18:05:47 +08:00
|
|
|
|
2025-02-05 18:07:53 +08:00
|
|
|
for c.scanner.Scan() {
|
|
|
|
line := c.scanner.Bytes()
|
|
|
|
item := make(map[string]any)
|
2024-03-22 18:05:47 +08:00
|
|
|
|
2025-02-05 18:07:53 +08:00
|
|
|
if err := json.Unmarshal(line, &item); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2024-03-22 18:05:47 +08:00
|
|
|
|
2025-02-05 18:07:53 +08:00
|
|
|
if len(fields) > 0 {
|
|
|
|
// todo: pick fields
|
|
|
|
}
|
2024-03-22 18:05:47 +08:00
|
|
|
|
2025-02-05 18:07:53 +08:00
|
|
|
list = append(list, item)
|
2024-03-22 18:05:47 +08:00
|
|
|
|
2025-02-05 18:07:53 +08:00
|
|
|
if len(list) >= limit {
|
|
|
|
return list, nil
|
|
|
|
}
|
2024-03-22 18:05:47 +08:00
|
|
|
}
|
|
|
|
|
2025-02-05 18:07:53 +08:00
|
|
|
return list, nil
|
2024-03-22 18:05:47 +08:00
|
|
|
}
|
|
|
|
|
2025-02-07 18:00:10 +08:00
|
|
|
func (c *client) WriteData(ctx context.Context, items []map[string]any) (int, error) {
|
2025-02-05 18:07:53 +08:00
|
|
|
total := 0
|
|
|
|
for _, item := range items {
|
|
|
|
bs, err := json.Marshal(item)
|
|
|
|
if err != nil {
|
|
|
|
return total, err
|
|
|
|
}
|
2024-03-22 18:05:47 +08:00
|
|
|
|
2025-02-05 18:07:53 +08:00
|
|
|
if _, err = c.f.Write(bs); err != nil {
|
|
|
|
return total, err
|
|
|
|
}
|
2024-03-22 18:05:47 +08:00
|
|
|
|
2025-02-05 18:07:53 +08:00
|
|
|
total++
|
2024-03-22 18:05:47 +08:00
|
|
|
|
2025-02-05 18:07:53 +08:00
|
|
|
if _, err = c.f.WriteString("\n"); err != nil {
|
|
|
|
return total, err
|
|
|
|
}
|
2024-03-22 18:05:47 +08:00
|
|
|
}
|
|
|
|
|
2025-02-05 18:07:53 +08:00
|
|
|
return total, nil
|
2024-03-22 18:05:47 +08:00
|
|
|
}
|
|
|
|
|
2025-02-07 18:00:10 +08:00
|
|
|
func (c *client) ReadMapping(ctx context.Context) (map[string]any, error) {
|
|
|
|
var (
|
|
|
|
err error
|
|
|
|
bs []byte
|
|
|
|
)
|
|
|
|
|
|
|
|
if bs, err = io.ReadAll(c.f); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
m := make(map[string]any)
|
|
|
|
|
|
|
|
if err = json.Unmarshal(bs, &m); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return m, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *client) WriteMapping(ctx context.Context, mapping map[string]any) error {
|
|
|
|
bs, err := json.Marshal(mapping)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
_, err = c.f.Write(bs)
|
|
|
|
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *client) ReadSetting(ctx context.Context) (map[string]any, error) {
|
|
|
|
var (
|
|
|
|
err error
|
|
|
|
bs []byte
|
|
|
|
)
|
|
|
|
|
|
|
|
if bs, err = io.ReadAll(c.f); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
m := make(map[string]any)
|
|
|
|
|
|
|
|
if err = json.Unmarshal(bs, &m); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return m, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *client) WriteSetting(ctx context.Context, setting map[string]any) error {
|
|
|
|
bs, err := json.Marshal(setting)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
_, err = c.f.Write(bs)
|
|
|
|
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2025-02-05 18:07:53 +08:00
|
|
|
func NewClient(path string, t model.IOType) (model.IO[map[string]any], error) {
|
2024-03-22 18:05:47 +08:00
|
|
|
var (
|
2025-02-05 18:07:53 +08:00
|
|
|
info os.FileInfo
|
|
|
|
err error
|
|
|
|
f *os.File
|
2024-03-22 18:05:47 +08:00
|
|
|
)
|
|
|
|
|
2025-02-05 18:07:53 +08:00
|
|
|
switch t {
|
|
|
|
case model.Input:
|
|
|
|
if info, err = os.Stat(path); err != nil {
|
|
|
|
return nil, err
|
2024-03-22 18:05:47 +08:00
|
|
|
}
|
|
|
|
|
2025-02-05 18:07:53 +08:00
|
|
|
log.Debug("input file: %s, size: %d", path, info.Size())
|
2024-03-22 18:05:47 +08:00
|
|
|
|
2025-02-05 18:07:53 +08:00
|
|
|
if f, err = os.Open(path); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
case model.Output:
|
|
|
|
if info, err = os.Stat(path); err == nil {
|
|
|
|
return nil, fmt.Errorf("file already exists: %s", path)
|
2024-03-22 18:05:47 +08:00
|
|
|
}
|
2025-01-22 17:29:12 +08:00
|
|
|
|
2025-02-05 18:07:53 +08:00
|
|
|
if !os.IsNotExist(err) {
|
|
|
|
return nil, err
|
|
|
|
}
|
2024-03-22 18:05:47 +08:00
|
|
|
|
2025-02-05 18:07:53 +08:00
|
|
|
if f, err = os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_TRUNC|os.O_APPEND, 0o644); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
return nil, fmt.Errorf("unknown type: %s", t)
|
2024-03-22 18:05:47 +08:00
|
|
|
}
|
|
|
|
|
2025-02-05 18:07:53 +08:00
|
|
|
c := &client{f: f, info: info}
|
|
|
|
buf := make([]byte, opt.BuffSize)
|
|
|
|
scanner := bufio.NewScanner(c.f)
|
|
|
|
scanner.Buffer(buf, opt.MaxBuffSize)
|
|
|
|
c.scanner = scanner
|
|
|
|
|
2024-03-22 18:05:47 +08:00
|
|
|
return c, nil
|
|
|
|
}
|