-
Notifications
You must be signed in to change notification settings - Fork 489
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for a paste operator in join.as() prefix specifications. #444
Changes from all commits
ff0777f
c94385c
717d10d
6489a4f
7bfdcc1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -31,16 +31,17 @@ import ( | |
// errors | ||
// |join(requests) | ||
// // Provide prefix names for the fields of the data points. | ||
// .as('errors', 'requests') | ||
// .as('errors', '#') | ||
// // points that are within 1 second are considered the same time. | ||
// .tolerance(1s) | ||
// // fill missing values with 0, implies outer join. | ||
// .fill(0.0) | ||
// // name the resulting stream | ||
// .streamName('error_rate') | ||
// // Both the "value" fields from each parent have been prefixed | ||
// // with the respective names 'errors' and 'requests'. | ||
// |eval(lambda: "errors.value" / "requests.value") | ||
// // The "value" field from the errors parent has been | ||
// // prefixed with 'errors.' but the "value" field from the requests parent has | ||
// // been copied without prepending an additional prefix. | ||
// |eval(lambda: "errors.value" / "value")) | ||
// .as('rate') | ||
// ... | ||
// | ||
|
@@ -90,11 +91,23 @@ func newJoinNode(e EdgeType, parents []Node) *JoinNode { | |
} | ||
|
||
// Prefix names for all fields from the respective nodes. | ||
// | ||
// Each field from the parent nodes will be prefixed with the provided name and a '.'. | ||
// See the example above. | ||
// | ||
// The names cannot have a dot '.' character. | ||
// | ||
// If a prefix is not specified or is empty, then field names from parent nodes | ||
// will be copied without attaching a prefix. | ||
// | ||
// If a prefix contains a trailing '#' character, then the prefix | ||
// upto, but not including the trailing '#' character is prepended to the field name | ||
// from the parent node without adding the '.' character after the prefix. | ||
// | ||
// It is the callers responsibility to ensure that when these rules are applied | ||
// the collection of output field names does not contain any duplicate names. Failure | ||
// to ensure this will result in a runtime error. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should the entire task be stopped because of a name conflict? I know that in the
Either extreme could be detrimental based on the use case but I think #1 is the worse of the two since is means possibly lots of data is dropped, while the task is off. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I believe that the task should be stopped since data it is likely that if a set of points fails the uniqueness test then all subsequent sets of points will also fail the test in which case joined data will be silently dropped from the output stream. |
||
// | ||
// tick:property | ||
func (j *JoinNode) As(names ...string) *JoinNode { | ||
j.Names = names | ||
|
@@ -137,25 +150,17 @@ func (j *JoinNode) validate() error { | |
return fmt.Errorf("a call to join.as() is required to specify the output stream prefixes.") | ||
} | ||
|
||
if len(j.Names) != len(j.Parents()) { | ||
if len(j.Names) > len(j.Parents()) { | ||
return fmt.Errorf("number of prefixes specified by join.as() must match the number of joined streams") | ||
} else if len(j.Names) < len(j.Parents()) { | ||
tmp := make([]string, len(j.Parents())) | ||
copy(tmp, j.Names) | ||
j.Names = tmp | ||
} | ||
|
||
for _, name := range j.Names { | ||
if len(name) == 0 { | ||
return fmt.Errorf("must provide a prefix name for the join node, see .as() property method") | ||
} | ||
if strings.ContainsRune(name, '.') { | ||
return fmt.Errorf("cannot use name %s as field prefix, it contains a '.' character", name) | ||
} | ||
} | ||
names := make(map[string]bool, len(j.Names)) | ||
for _, name := range j.Names { | ||
if names[name] { | ||
return fmt.Errorf("cannot use the same prefix name see .as() property method") | ||
} | ||
names[name] = true | ||
} | ||
|
||
return nil | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we remove the panic here and return an error instead?
The calling functions
JoinInto*
can then log the error andreturn models.Point/Batch{},false
the join will be skipped.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I made use of panic because it complicates every caller of outName which would otherwise have to check for an error.
update: I had a quick look at removing the panic - it really does make things quite messy. However, if you really want me to do that, let me know and I will push such a change