Skip to content

Commit d5f6e1f

Browse files
committed
refactor import dry run to handle custom function and body
1 parent 7996317 commit d5f6e1f

File tree

3 files changed

+65
-20
lines changed

3 files changed

+65
-20
lines changed

base/error.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,8 @@ var (
8383

8484
// ErrInvalidJSON is returned when the JSON being unmarshalled cannot be parsed.
8585
ErrInvalidJSON = HTTPErrorf(http.StatusBadRequest, "Invalid JSON")
86+
87+
ErrImportDryRun = &sgError{"Error occured during import dry run: "}
8688
)
8789

8890
func (e *sgError) Error() string {

db/import.go

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -545,20 +545,44 @@ func (i *ImportFilterFunction) EvaluateFunction(ctx context.Context, doc Body, d
545545
return false, errors.New("Import filter function returned non-boolean value.")
546546
}
547547
}
548-
func (db *DatabaseCollectionWithUser) ImportFilterDryRun(ctx context.Context, doc Body, docid string) (bool, error) {
549-
550-
importFilter := db.importFilter()
551-
if docid != "" {
552-
docInBucket, err := db.GetDocument(ctx, docid, DocUnmarshalAll)
553-
if err == nil {
554-
if doc == nil {
555-
doc = docInBucket.Body(ctx)
548+
549+
// ImportFilterDryRun Runs a document through the import filter and returns a boolean and error
550+
func (db *DatabaseCollectionWithUser) ImportFilterDryRun(ctx context.Context, doc Body, importFn string) (bool, error) {
551+
552+
var shouldImport bool
553+
if importFn == "" {
554+
importFilter := db.importFilter()
555+
ouput, err := importFilter.EvaluateFunction(ctx, doc, true)
556+
if err != nil {
557+
if errors.Is(errors.New("Import filter function returned non-boolean value."), err) {
558+
err = fmt.Errorf("%s: %s ", base.ErrImportDryRun, err)
556559
}
557-
} else {
560+
return false, err
561+
}
562+
shouldImport = ouput
563+
} else {
564+
jsTimeout := time.Duration(base.DefaultJavascriptTimeoutSecs) * time.Second
565+
importRunner, err := newImportFilterRunner(ctx, importFn, jsTimeout)
566+
if err != nil {
567+
return false, errors.New("Import filter function error: " + err.Error())
568+
}
569+
importOuput, err := importRunner.Call(ctx, doc)
570+
switch result := importOuput.(type) {
571+
case bool:
572+
shouldImport = result
573+
break
574+
case string:
575+
boolResult, err := strconv.ParseBool(result)
576+
if err != nil {
577+
return false, err
578+
}
579+
shouldImport = boolResult
580+
break
581+
default:
582+
err = fmt.Errorf("%s Import filter function returned non-boolean result %v Type: %T", base.ErrImportDryRun, result, result)
558583
return false, err
559584
}
560585
}
561-
shouldImport, err := importFilter.EvaluateFunction(ctx, doc, true)
562586

563-
return shouldImport, err
587+
return shouldImport, nil
564588
}

rest/diagnostic_doc_api.go

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ licenses/APL2.txt.
1111
package rest
1212

1313
import (
14-
"fmt"
1514
"mime"
1615
"net/http"
1716

@@ -39,6 +38,11 @@ type SyncFnDryRunPayload struct {
3938
Doc db.Body `json:"doc,omitempty"`
4039
}
4140

41+
type ImportFilterDryRunPayload struct {
42+
Function string `json:"sync_function"`
43+
Doc db.Body `json:"doc,omitempty"`
44+
}
45+
4246
func populateDocChannelInfo(doc db.Document) map[string][]auth.GrantHistorySequencePair {
4347
resp := make(map[string][]auth.GrantHistorySequencePair, len(doc.Channels))
4448

@@ -119,18 +123,33 @@ func (h *handler) handleSyncFnDryRun() error {
119123
// HTTP handler for running a document through the import filter and returning the results
120124
func (h *handler) handleImportFilterDryRun() error {
121125
docid := h.getQuery("doc_id")
126+
contentType, _, _ := mime.ParseMediaType(h.rq.Header.Get("Content-Type"))
122127

123-
body, err := h.readDocument()
124-
if err != nil {
125-
if docid == "" {
126-
return fmt.Errorf("Error reading body: %s, no doc id provided for dry run", err)
127-
}
128+
if contentType != "application/json" && contentType != "" {
129+
return base.HTTPErrorf(http.StatusUnsupportedMediaType, "Invalid Content-Type header: %s. Needs to be empty or application/json", contentType)
128130
}
129131

130-
if docid != "" && body != nil {
131-
return base.HTTPErrorf(http.StatusBadRequest, "doc body and doc id provided. Please provide either the body or a doc id for the import filter dry run")
132+
var importFilterPayload ImportFilterDryRunPayload
133+
err := h.readJSONInto(&importFilterPayload)
134+
// Only require a valid JSON payload if docid is not provided.
135+
// If docid is provided, the sync function will use the document from the bucket, and the payload is optional.
136+
if err != nil && docid == "" {
137+
return base.HTTPErrorf(http.StatusUnprocessableEntity, "Error reading sync function payload: %v", err)
138+
}
139+
140+
//if docid != "" && body != nil {
141+
// return base.HTTPErrorf(http.StatusBadRequest, "doc body and doc id provided. Please provide either the body or a doc id for the import filter dry run")
142+
//}
143+
144+
var doc db.Body
145+
if docid != "" {
146+
docInBucket, err := h.collection.GetDocument(h.ctx(), docid, db.DocUnmarshalSync)
147+
if err != nil {
148+
return err
149+
}
150+
doc = docInBucket.Body(h.ctx())
132151
}
133-
shouldImport, err := h.collection.ImportFilterDryRun(h.ctx(), body, docid)
152+
shouldImport, err := h.collection.ImportFilterDryRun(h.ctx(), doc, importFilterPayload.Function)
134153
errorMsg := ""
135154
if err != nil {
136155
errorMsg = err.Error()

0 commit comments

Comments
 (0)