Provide entry count
This commit is contained in:
@@ -2,6 +2,8 @@ package decoder
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/cortezaproject/corteza-server/pkg/count"
|
||||
)
|
||||
|
||||
type (
|
||||
@@ -17,12 +19,14 @@ type (
|
||||
}
|
||||
|
||||
flatReader struct {
|
||||
f io.ReadSeeker
|
||||
r FlatReader
|
||||
header []string
|
||||
more bool
|
||||
}
|
||||
|
||||
structuredDecoder struct {
|
||||
f io.ReadSeeker
|
||||
header []string
|
||||
d StructuredDecoder
|
||||
buf []map[string]interface{}
|
||||
@@ -34,13 +38,27 @@ type (
|
||||
)
|
||||
|
||||
// flat reader
|
||||
func NewFlatReader(r FlatReader) *flatReader {
|
||||
func NewFlatReader(r FlatReader, f io.ReadSeeker) *flatReader {
|
||||
return &flatReader{
|
||||
f: f,
|
||||
r: r,
|
||||
more: true,
|
||||
}
|
||||
}
|
||||
|
||||
func (dec *flatReader) EntryCount() (uint64, error) {
|
||||
defer dec.f.Seek(0, 0)
|
||||
|
||||
c, err := count.Lines(dec.f)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if c <= 0 {
|
||||
return 0, nil
|
||||
}
|
||||
return c - 1, nil
|
||||
}
|
||||
|
||||
func (dec *flatReader) get(fnc fdCallback) error {
|
||||
v, err := dec.r.Read()
|
||||
if err == io.EOF {
|
||||
@@ -76,12 +94,18 @@ func (dec *flatReader) Header() []string {
|
||||
}
|
||||
|
||||
// structured decoder
|
||||
func NewStructuredDecoder(d StructuredDecoder) *structuredDecoder {
|
||||
func NewStructuredDecoder(d StructuredDecoder, f io.ReadSeeker) *structuredDecoder {
|
||||
return &structuredDecoder{
|
||||
f: f,
|
||||
d: d,
|
||||
}
|
||||
}
|
||||
|
||||
func (dec *structuredDecoder) EntryCount() (uint64, error) {
|
||||
defer dec.f.Seek(0, 0)
|
||||
return count.Lines(dec.f)
|
||||
}
|
||||
|
||||
func (dec *structuredDecoder) get(fnc sdCallback) error {
|
||||
if !dec.d.More() {
|
||||
return nil
|
||||
|
||||
@@ -77,6 +77,7 @@ type (
|
||||
|
||||
Decoder interface {
|
||||
Header() []string
|
||||
EntryCount() (uint64, error)
|
||||
Records(fields map[string]string, Create decoder.RecordCreator) error
|
||||
}
|
||||
|
||||
@@ -96,6 +97,7 @@ type (
|
||||
RecordImportProgress struct {
|
||||
StartedAt *time.Time `json:"startedAt"`
|
||||
FinishedAt *time.Time `json:"finishedAt"`
|
||||
EntryCount uint64 `json:"entryCount"`
|
||||
Completed uint64 `json:"completed"`
|
||||
Failed uint64 `json:"failed"`
|
||||
FailReason error `json:"failReason"`
|
||||
|
||||
@@ -175,6 +175,7 @@ func (ctrl *Record) ImportInit(ctx context.Context, r *request.RecordImportInit)
|
||||
var (
|
||||
err error
|
||||
recordDecoder service.Decoder
|
||||
entryCount uint64
|
||||
)
|
||||
|
||||
// Access control.
|
||||
@@ -204,15 +205,19 @@ func (ctrl *Record) ImportInit(ctx context.Context, r *request.RecordImportInit)
|
||||
// determine decoder
|
||||
switch strings.ToLower(ext) {
|
||||
case "json", "jsonl", "ldjson", "ndjson":
|
||||
recordDecoder = decoder.NewStructuredDecoder(json.NewDecoder(f))
|
||||
recordDecoder = decoder.NewStructuredDecoder(json.NewDecoder(f), f)
|
||||
|
||||
case "csv":
|
||||
recordDecoder = decoder.NewFlatReader(csv.NewReader(f))
|
||||
recordDecoder = decoder.NewFlatReader(csv.NewReader(f), f)
|
||||
|
||||
default:
|
||||
return nil, errors.New(fmt.Sprintf("unsupported format (\"%s\")", ext))
|
||||
|
||||
}
|
||||
entryCount, err = recordDecoder.EntryCount()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
header := recordDecoder.Header()
|
||||
hh := make(map[string]string)
|
||||
@@ -220,7 +225,14 @@ func (ctrl *Record) ImportInit(ctx context.Context, r *request.RecordImportInit)
|
||||
hh[h] = ""
|
||||
}
|
||||
|
||||
return ctrl.importSession.SetRecordByID(ctx, 0, r.NamespaceID, r.ModuleID, hh, nil, recordDecoder)
|
||||
return ctrl.importSession.SetRecordByID(
|
||||
ctx,
|
||||
0,
|
||||
r.NamespaceID,
|
||||
r.ModuleID,
|
||||
hh,
|
||||
&service.RecordImportProgress{EntryCount: entryCount},
|
||||
recordDecoder)
|
||||
}
|
||||
|
||||
func (ctrl *Record) ImportRun(ctx context.Context, r *request.RecordImportRun) (interface{}, error) {
|
||||
|
||||
28
pkg/count/file.go
Normal file
28
pkg/count/file.go
Normal file
@@ -0,0 +1,28 @@
|
||||
package count
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
)
|
||||
|
||||
// Lines provides a line count
|
||||
//
|
||||
// https://stackoverflow.com/a/24563853
|
||||
func Lines(r io.ReadSeeker) (count uint64, err error) {
|
||||
defer r.Seek(0, 0)
|
||||
buf := make([]byte, 32*1024)
|
||||
lineSep := []byte{'\n'}
|
||||
|
||||
for {
|
||||
c, err := r.Read(buf)
|
||||
count += uint64(bytes.Count(buf[:c], lineSep))
|
||||
|
||||
switch {
|
||||
case err == io.EOF:
|
||||
return count, nil
|
||||
|
||||
case err != nil:
|
||||
return count, err
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user