Fix UniqueOpts.ExcludeKind being silently ignored by isEmpty() - #1404
Conversation
6fb21b7 to
e797f26
Compare
|
@JackDanger Thanks!! Could you sign the CLA please? A small bug in the new validation is that this shape of UniqueOpts{
ExcludeKind: true,
ByState: rivertype.UniqueOptsByStateDefault(),
}We could modify your logic to also allow UniqueOpts{ExcludeKind: true}I wonder if maybe what we should do here is keep the |
e797f26 to
6eeeb85
Compare
|
Thanks Jack! @bgentry Can I get your opinion on this one as well? I suggested to Jack that we drop validation in favor of allowing |
|
signed! riverqueue/rivercla#36 I'm looking for ways to make this a little more elegant and I appreciate the review and feedback 🙇 |
|
@JackDanger Thanks :) Ugh, I hate to do this, but I was thinking about this more tonight, and I think what you had originally was probably better. Allowing What do you think about resurrecting a validation like this? if o.ExcludeKind && !o.ByArgs && !o.ByQueue && o.ByPeriod == 0 {
return errors.New("UniqueOpts.ExcludeKind requires ByArgs, ByQueue, or ByPeriod")
}And in case we ever get a complaint about it, we could reevaluate. Sorry about the flip flop :/ I should have thought harder about this when I suggested the original change. |
The public UniqueOpts.isEmpty() does not consider ExcludeKind, against the warning in its own doc comment, while dbunique.UniqueOpts.IsEmpty() in internal/dbunique does. A UniqueOpts with only ExcludeKind set is therefore treated as unset by insertParamsFromConfigArgsAndOptions, and uniqueness silently never applies. - TestUniqueOpts_isEmpty now asserts both isEmpty implementations agree for every field permutation. - TestUniqueOpts_validateExcludeKind asserts an ExcludeKind-only config is rejected (the resulting key would be constant across the whole table). - Two subtests in TestInsertParamsFromJobArgsAndOptions cover rejection via the real insert-params path and key equality across kinds with ByArgs+ExcludeKind. These tests fail until the isEmpty()/validate() fix lands.
The public UniqueOpts.isEmpty() never considered ExcludeKind — against the explicit warning in its own doc comment — even though d977e10 added the field alongside the same option inside internal/dbunique, whose IsEmpty() does consider it. Callers passing only UniqueOpts{ExcludeKind: true} therefore had no unique key computed at all: jobs were inserted with no dedup, silently, while the option's doc promised uniqueness "across all jobs regardless of kind". - isEmpty() now counts ExcludeKind, matching dbunique.UniqueOpts.IsEmpty(). - validate() rejects the ExcludeKind-only combination: the unique key is built from kind/args/queue/period, so kind excluded and nothing else included leaves no key to dedupe by. The combination is safe to re-evaluate if a justified use shows up, per review. - The UniqueOpts.ExcludeKind doc comment states the combination requirement. Signed-off-by: Jack Danger <github@jackcanty.com>
6eeeb85 to
8e3ef79
Compare
|
Thanks Brandur, addressed in 8e3ef79 |
UniqueOpts.ExcludeKindis silently ignored on master. The publicisEmpty()never looks at it — despite its own doc comment warning that every new option must be added there — while the copy of the same opts ininternal/dbunique(dbunique.UniqueOpts.IsEmpty()) does count it. SoUniqueOpts{ExcludeKind: true}inserts jobs with no unique key at all, and when a worker also carries unique opts, those silently override the caller's instead.Two commits: first the failing test (
TestUniqueOpts_isEmptyasserts the public and internalisEmptyagree for every field combination), then the fix — just theisEmpty()one-liner. Acceptance tests pin the insert-params path around it.After review, the corner config
{ExcludeKind: true}with nothing else set stays valid: it now applies uniqueness across all jobs (a whole-table key, sinceByStatedefaults toUniqueOptsByStateDefault()when unset) instead of being silently ignored.Reproduce on master with just the test commit:
(the acceptance tests in the branch stay green on master too — the twin-parity assertion is the one that fails.)