3
0

Provide entry count

This commit is contained in:
Tomaž Jerman
2019-08-29 10:07:52 +02:00
parent a8b5e3b063
commit 986c69a812
4 changed files with 71 additions and 5 deletions

View File

@@ -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

View File

@@ -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"`

View File

@@ -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
View 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
}
}
}