Commit graph

681 commits

Author SHA1 Message Date
rachithrr
3e42fc7d9f
WIP: Sort extract columns by a field (#2193)
* FB-1251: Add ability to sort Extract queries by some field

There is a sort call which takes a row call and the field, and
based on the field type, the corresponding rows are read. both key and
value are stored in RowKV{}. The value is stored since its required to
merge data from shards. values are sorted in each shard and these sorted
listes are merged in the reduce.
sort-desc flag is sent to comparator to decide the sorting order. ok
flag is added to the compare function to track any error in the
sort.Slice anonymous function
Sorting over set field was removed, since there would be multiple values
for each ids and there would be no right sorting order there.
2022-08-19 13:29:17 -05:00
Samir Patel
3681feeeb2
[FB-1024 FB-1590] Increase timerange (un-revert) (#2174)
previously we allowed users to specify a granularity for timestamp
e.g. seconds, milli, micro, nano
however we converted everything to nano before we stored it.
This reduced the allowed range for all time units to what
was allowed by timestamp. For example, with second granularity
you can represent billions of years within the capacity of
int64 but with nano its somewhere b/w 100-200 years.

So now, for timeunits of seconds, milli, and micro the range
is year 0001 - 9999. These limits come from what Go
supports.

So this uses unit specific function to translate
timestamps to values and vice versa to increase
the time range.

In the process of increasing the range for timestamp and subsequent
testing, I found and addressed a few bugs:
- min/max queries were not using timestamp specific comparators so
  added that.
- Values from Import/ingest come to FB as relative values to epoch
    whereas other BSI fields come as actual values and then
    becomes relative to their respective bases within FB. so some
    specific handling of that was added.
- However! Set queries use timestamp strings which are, of course,
    the actual value they designate. So they have to become
    relative.
- When bitdepth is 0, Min/maxUnsigned functions did not run
resulting in a count of 0 when there
was an actual value that was 0.

Also, this removes (now) dead code and updates/adds tests.
2022-08-04 15:20:45 -07:00
reesporte
89159134a4 recalculate shards for each call in query if it needs them
this way we don't have write/read calls in the same query that return false
results because they're using stale shards.
2022-07-27 10:25:52 -05:00
Seebs
b3a4e52a13 simplify, streamline, and possibly debug embedded etcd
The root problem this is attempting to address is sporadic
weird cases in which etcd mistakenly thinks it's down even when
it's up. I am not confident that this is addressed, but there's
a reasonable chance that it is, and I can't trigger it at the
moment, but it was always sporadic, so that doesn't prove much.

There's a lot going on here, and it comes into roughly three
categories.

First: Dropping unused/unneeded code. There's a lot of leftover
bits from the initial development and refactoring of this.

Second: Unifying and shuffling some of the design. We had
multiple interfaces which are functionally impossible to
usefully implement separately, so they're combined together,
and in some cases, moved.

Third: Streamlining logic and simplifying design choices.

This is combined into one commit because the changes are
thoroughly entertwined with each other and you can't usefully
break most of them out.

Also, a bunch of test coverage for most of these changes.

Big changes:

We merge the topology and disco packages.  The topology and disco
packages being separate creates a complicated tangle of problems
and dependencies.  The fundamental problem, approximately, is that
topology.Node has to track disco.NodeState.

There's three core interfaces interacting here:
	topology.Noder (maintains list of nodes)
	disco.Stator (maintains the state of a node)
	disco.Metadator (stores, possibly retrieves, node metadata)
But the node state mantained by the Noder *is* the set of node
metadata, plus state updates produced by Stators. The only actual
non-trivial and usable implementation of these interfaces is a single
thing which implements all three, and in which the implementations
share a single backend data source which they are all modifying.

But you can't move Noder into disco, because Noder has to refer
to topology.Node, but topology.Node refers to disco.

Solution: First, merge these two packages. Second, merge these
three interfaces, to provide a single interface which is more
clear about the fact that (metadator.)SetMetadata() and
(stator.)Started() are both changing the output we'll get from
(noder.)Nodes().

We rework the node state tracking.

We have this nodeStates map which is almost unused. Really, we
don't need it at all. Every node's state is either its last heartbeat
state or "Unknown", so we simplify this a bit. Also, we ensure that
the populateNodeStates function itself is yielding the sorted nodes
list, so we don't have to be as worried about possible later lookups
of sortedNodes happening outside a lock. We also add diagnostics
for deleting nodes from the metadata list (this should never happen),
and try to track heartbeat state more closely.

This is *probably* what fixes the underlying reported problem,
if anything did.

Still an open issue: Make heartbeat state changes aware of when
they're talking about *this* node and possibly not try to
mark it down? Except this may have a flaw: That would result in
each node disagreeing with other nodes in etcd about the state
of that node in the failure cases, and undermine the point of
using etcd to keep these states consistent.

We reduce the number of contexts and cancelfuncs in the etcd wrapper.

We create a shared context for the non-etcd.embed children of our
etcd wrapper, the heartbeat/keepalive and the node watcher, so we
can cancel that one context and cancel all of those at once, so
we don't need to separately track a function to call to cancel
the watch, AND be closing another channel. Also, our shutdown
now propagates automatically to the various etcd API calls we've
made for things like the node watcher and keepalive calls.

We still need to watch that channel in watchNodesOnce, though,
because apparently the watch doesn't yield an error even if the
context calling it is canceled. Whee.

This should reduce the risk of ending up in an inconsistent state,
and also the Close() function is probably idempotent now.

Smaller changes:

* Remove config-generators that existed to generate etcd
  configs but were used only for tests that no longer exist
  or make sense.
* Move the logic to generate etcd configs into the etcd
  package, instead of the "testing" subpackage. This allows
  us to write a self-contained config generator for
  clusters where the nodes know about each other, but do
  this just with etcd, not with full featurebase servers.
* Move the thing generating `fake:%d` socket names into
  the etcd package, which is the only place we use it.
  Also simplify it slightly.
* Don't panic on invalid URLs, report errors from them.
* At least try to use etcd's config.Validate functionality.
  It's underdocumented, so we're not sure what it will report,
  but at least if it does we'll get reports from it and
  know what they are?
* Try to handle CompactRevision errors from watches more
  correctly -- after a CompactRevision, any future attempt
  to watch from a lower revision will necessarily fail, so
  we adjust our target revision up. We don't have good
  testing for this.
* Drop the Metadata() method (that used to be in Metadator)
  because nothing ever used it and it didn't make much sense
  to try.
* Convert SetMetadata from taking an arbitrary json blob
  to taking the only data that would ever be valid since
  we always use it to extract node information anyway.
* Drop several unused functions, unexport things only used
  internally.
* Replace Started() with SetState("STARTED"), allowing us
  to write tests that mess with states. We weren't really thinking
  carefully about state transitions sometimes and now it's much
  easier to do that thinking.
* Stop leaving stray localhost:2380 and localhost:2379 in
  our embed config. We still sometimes see peer requests from
  those and I honestly don't know why, but at least it should
  be rarer.
2022-07-21 11:42:35 -05:00
souhailanoor
5451312515
Changes to row queries with from/to options (#2152)
Changes to row queries with from/to options return an error if field is not a timestamp field
logic couldn't be made earlier in call stack because other queries process from/to time differently.
2022-07-20 15:10:41 -05:00
tgruben
ccbc944eea
standard code already in viewsByTimeRange (#2149) 2022-07-18 13:48:25 -05:00
Samir Patel
33a916c0f4 Revert "increase time range for timestamp by using specified granularity"
This PR reverts the timestamp work.

The timestamp work requires changes to FB and IDK; and there are
circular dependencies between tests in either repo preventing merging
of either. The work here is pretty stable, but required bypassing
the smoketest. Meanwhile, I found some additional things in IDK that
need addressing which means I merged this work in pre-maturely. Once
I get that worked out, I'll re-commit these commits.

This reverts following commits related to timestamp work:

bypass of smoke test b/c of circular dep with IDK: 0676790
update codec to reflect changes to timstamp range: bd5dc76
fix few bugs regarding timestamp: 33fce8a
increase time range for timestamp by using specified granularity: 5939923.
2022-07-18 11:09:04 -05:00
tgruben
d348cc65e9
[FB-1593] add from/to support to extract row call (#2148)
* add from/to support to extract row call

* gofmt
2022-07-15 18:17:59 -05:00
Samir Patel
bd5dc760b7 update codec to reflect changes to timstamp range
also address a few minor feedback comments from review
2022-07-15 15:15:12 -05:00
Samir Patel
33fce8a05b fix few bugs regarding timestamp
In the process of increasing the range for timestamp and subsequent
testing, I found and addressed a few bugs:
- min/max queries were not using timestamp specific comparators so
  added that.
- Values from Import/ingest come to FB as relative values to epoch
    whereas other BSI fields come as actual values and then
    becomes relative to their respective bases within FB. so some
    specific handling of that was added.
- However! Set queries use timestamp strings which are, of course,
    the actual value they designate. So they have to become
    relative.
- When bitdepth is 0, Min/maxUnsigned functions did not run
resulting in a count of 0 when there
was an actual value that was 0.

Also, this removes (now) dead code and updates/adds tests.
2022-07-15 15:15:12 -05:00
Samir Patel
593992312a increase time range for timestamp by using specified granularity
previously we allowed users to specify a granularity for timestamp
e.g. seconds, milli, micro, nano
however we converted everything to nano before we stored it.
This reduced the allowed range for all time units to what
was allowed by timestamp. For example, with second granularity
you can represent billions of years within the capacity of
int64 but with nano its somewhere b/w 100-200 years.

So now, for timeunits of seconds, milli, and micro the range
is year 0001 - 9999. These limits come from what Go
supports.

So this uses unit specific function to translate
timestamps to values and vice versa to increase
the time range.
2022-07-15 15:15:12 -05:00
Seebs
97c84da566 fix race condition in executor shutdown 2022-06-21 17:03:09 -05:00
reesporte
0d91e2991d Revert "FB-1491: Revert pql.Decimal commit for the 4.8.5 release (#2117)"
This reverts commit acbcec54c8.
2022-06-17 14:58:30 -05:00
rachithrr
acbcec54c8
FB-1491: Revert pql.Decimal commit for the 4.8.5 release (#2117)
* Revert "make pql.Decimal.Value a private big.Int field"

This reverts commit eab6174388.

* Revert "pql.Decimal for DecimalVal in ValCount&GroupCount"

This reverts commit a0c9eec410.

* Revert "Add AddDecimal support to pql"

This reverts commit 50787fd37a.
2022-06-15 09:15:37 -07:00
seebs
42b4c05df2
Implement UnionRows as a BitmapFilter (#2116)
This is fairly experimental, but basically, we make a fragment-level
op which, given a []uint64, can produce a union of all those rows in
the fragment, with a single scan through the fragment and not needing
a ton of additional space to reify all the rows at once.

Now with the Repair calls happening in the Results assembly rather than
on the intermediate data.
2022-06-15 08:40:12 -07:00
reesporte
eab6174388 make pql.Decimal.Value a private big.Int field
This ensures that we can't overflow when adding `pql.Decimal`s together. The
only place we can possibly overflow is when converting pql.Decimal to an Int64,
but that is a risk we have to take. Also, the only place we do this is in our
ToRowser. We could maybe change that to strings, so the presentation of data
doesn't indicate an overflow, but that is a later decision to make. It will
also involve fixing the generate-proto-grpc make command, because that's broken
rn.
2022-06-06 16:44:01 -05:00
reesporte
a0c9eec410 pql.Decimal for DecimalVal in ValCount&GroupCount
This way we can avoid annoying floating point rounding errors.

Check out FB-1359 for an example:
```
--- FAIL: TestExecutor_GroupByStrings (0.55s)
    --- FAIL: TestExecutor_GroupByStrings/3 (0.00s)
        executor_test.go:5433: unexpected result at 0:
             got:{Group:[generals.1.r1] Count:5 Agg:2775
DecimalAgg:27.749999999999996}
            want:{Group:[generals.1.r1] Count:5 Agg:2775 DecimalAgg:27.75}
```
2022-06-06 16:44:01 -05:00
reesporte
964f14a3a1
If the field doesn't exist return ErrFieldNotFound (#2081)
This way we don't return seemingly valid data for calls on non-existent fields. See
also [FB-237](https://molecula.atlassian.net/browse/FB-237).
2022-05-26 16:45:10 -05:00
reesporte
2d937728fa
remove vestigial print statement (#2080) 2022-05-26 09:33:43 -05:00
Matthew Jaffee
8e5ab106dc
FB-1459 ugly first cut at supportings Rows(in=[...]) (#2066)
* ugly first cut at supportings Rows(in=[...])

need tests, better handling of various combinations of arguments and
error cases

* explicitly error when other arguments passed with 'in' to Rows

* first cut at supporting Rows(in=[...])

'in' is explicitly not supported with any other arguments (except the
field of course), and will error. It works both as a standalone Rows
call and in GroupBy.

* bitmapfilter require ordered rowids

* remove log message

Co-authored-by: Todd Gruben <todd@molecula.com>
2022-05-25 11:57:59 -05:00
Samir Patel
68e72c2ce0
[FB-1435] BSI Base Fix (#2056)
* add bsi base back to int value

* test bsi base/min/max for IntFields

motivated by bsi base not being added back to values
in extract calls when min was a positive integer.
2022-05-13 09:33:53 -04:00
Matthew Jaffee
c554adb70a convert executor.shutdown to channel to avoid data race
Here was the race:
https://gitlab.com/molecula/featurebase/-/jobs/2391959728
2022-04-28 14:09:32 -05:00
Matthew Jaffee
02663d0282 when calculating what nodes can process a shard allow UNKNOWN state
we have an issue where nodes get into UNKNOWN state rather frequently
during periods of high load when they aren't actually down. We want to
allow queries in this situation rather than giving a "shard
unavailable" message.
2022-04-28 14:09:32 -05:00
Matthew Jaffee
dee46d4423 add PartitionToNodeAssignment as a new option
We default to the jmp-hash method which we had previously, and allow a
user to set the "modulus" option which uses a simple mod operation to
ensure an even spread of partitions across nodes.

I think that ideally we would have new indexes uses modulus and
existing indexes use jmp-hash which implies supporting this
configuration on a per-index basis.

If we don't do per index, we should probably run the whole test suite
both ways.
2022-04-27 17:21:47 -05:00
reesporte
96df2700fd save space when union-ing DistinctTimestamps
By using an empty struct, we reduce memory usage by
up to 16 bytes (the size of a timestamp string)
2022-04-14 10:31:56 -05:00
reesporte
bff9128c9b properly thread the ctx through so we can pass Auth around 2022-04-14 09:37:32 -05:00
Seebs
852a8be45a use ApplyRewriter for ClearRecords
This uses the shiny new ApplyRewriter logic for ClearRecords,
mostly to verify that ApplyRewriter works at all.

This also implies separating the cache update code out from
importPositions so it can be used also by this.

We also use fragment.ClearRecords instead of the different clearFragment
code in executor.  The clearFragment implementation did not update TopN
caches and the like. Standardize it on the clearRecords implementation
which does.
2022-04-12 12:24:22 -05:00
reesporte
66def7678c Implement ToRowser interface for DistinctTimestamp
Because the ToRowser interface was not implemented for DistinctTimestamp, there was
a error when using the GRPC endpoint to call Distinct(All(), field=ts). Implementing
the ToRowser interface for DistinctTimestamp solves that problem.

Related to SUP-210: WebUI, Python - Distinct() does not work for Timestamp field
2022-04-11 10:38:37 -05:00
Seebs
9f2b888c4f standardize and correct time range handling
If you're wondering how something that simple gets a commit
message this long, sit down, because you are in for a ride.

The Row, Rows, TopK, and GroupBy(Rows...) commands had three
different sets of semantics for from/to ranges. We unify these.
Sounds easy, right?

The original purpose of this was to address a bug in GroupBy
where, if you had multiple queries only one of which used time,
we could end up silently returning no results because we tried to
do a time query against a non-time field. This was easy to
fix; just move a boolean flag from outside a loop to inside
the loop so it resets to false on each pass.

In the process of trying to test that, I discovered that
specifying `from=...` without `to=...` in a Rows in a GroupBy
didn't work. Searching around, I discovered that we had three
different answers:

	GroupBy, TopK: unspecified 'to=' is 0
	Row: unspecified to is tomorrow
	Rows: unspecified to is the max time quantum in the field

(A time value of 0 is apparently interpreted as January 1st,
0001.) Note that "GroupBy" is really referring to a Rows()
command in a GroupBy, it's just that this uses completely different
code (because it has to be computing rows potentially matching or
restricted to a filter, or provide the rows it generated so
they can be used to filter something else).

So we fixed that, and made a field method for finding the min/max
values (as done in a Rows command that *isn't* in a GroupBy),
and tried to use that with viewsByTimeRange. Then I tried to write
documentation for this, but the documentation was unclear, and
I tried to clear it up. Which caused me to discover that these
four different places ALSO differed in when or whether they'd
replace a broad query with "just the standard view".

So. Round two of the fix: We create a `field.viewsByTimeRange`,
which tries to fall back to a standard view when one exists
and the specified range covers everything, and treats zero
values as non-restrictive, but also picks a narrow range that
is actually related to the range of dates in the field. This
matters because viewsByTimeRange generates the entire set of
views it would need *even if those views don't exist*.

We drop one test that was testing Rows specifically to verify
that, if you omitted To, we acted as though you'd specified a date
two days in the future. That behavior is not now intended, so
we drop the test that tries to verify it.

Thing that might make this better: Figuring out a way to generate the
list of views more cheaply. Right now, we're redoing all the view
computation, including producing a sorted list of view names, for
every shard. This is excessive, but hard to fix.

In particular, there is no trivial way to generate a sorting such
that you can take slices of it and have them be the right slices,
because we want to skip smaller time quanta when an entire larger
parent quantum is included. e.g., if we're including all of
April 2022, we don't want to include any of the days for April of
2022, but if we're doing up through April 15th, we want to include
the first 15 days of April, but NOT include the whole-month quantum.
And so on. Fixing this cleanly is hard and would require a
significant design effort.
2022-04-08 14:19:36 -05:00
Todd Gruben
9e3a2bba15 revert remove channel 2022-03-25 15:50:54 -05:00
rachithrr
d7c561aa7d FB-1281: FeatureBase crashes when Row call with "==" in Delete
- the EQ goes through HasConditionArg(), but the error wasn't caught
in the case of Delete.
2022-03-21 15:40:39 -05:00
tgruben
3a59421e3b
Merge branch 'master' into FB-1185 2022-03-14 14:30:37 -05:00
Todd Gruben
f9ee18b8b0 review suggestions 2022-03-14 14:18:21 -05:00
Ben Johnson
01e8a59f76 Remove unnecessary worker pool mutex 2022-03-14 09:56:08 -06:00
Todd Gruben
e64dde0b4c remove round trip 2022-03-11 06:20:07 -06:00
Todd Gruben
82d3f54a28 new delete flow to allow for qcx reset 2022-03-11 06:20:07 -06:00
Todd Gruben
e209759283 make maxdelete an optional param 2022-03-11 06:20:07 -06:00
Todd Gruben
1a8989a69b . 2022-03-11 06:20:07 -06:00
Todd Gruben
eff54f49a6 qcx finish/reset 2022-03-11 06:20:07 -06:00
Todd Gruben
d322cc7aef batch size 65536 2022-03-11 06:20:07 -06:00
tgruben
7fbcfdcd17
Merge branch 'master' into FB-1185 2022-02-28 09:42:15 -06:00
Todd Gruben
376af2c25f adust logic to include normalFlow vs recovery after merge 2022-02-28 08:12:03 -06:00
Samir Patel
05e98ee678 Check "like" argument applied to keyed fields
Check if queries that have a 'like' argument are applied to keyed
fields. If not, log that the user is trying to use 'like' on an
unsupported field type (as opposed to reporting that there
are no results.)
2022-02-25 16:54:19 -06:00
Todd Gruben
ecaaddcf71 . 2022-02-25 16:23:54 -06:00
Todd Gruben
e64767a886 merge with master 2022-02-25 16:23:54 -06:00
Todd Gruben
cf1de78efd remove string keys on delete to allow for reuse 2022-02-25 16:23:54 -06:00
Souhaila Noor
8a95ac344b We check for incomplete deletion when server is started.
When deletion is started, _exists field is updated with row+1.
After deletion is completed, we delete _exists=row+1.
If _exists>=1, then deletion was not completed.

Updated go version in docker to match other requirements.
Removed duplicate error check for grpc.
2022-02-25 09:28:13 -06:00
Seebs
2aa10670fb don't segfault for me, empty distinct results on timestamp field
There's an obvious bug, plus another bug that I hit trying to reproduce
the first bug, plus another... it's a long story.

Basically: If you get nothing back from executeDistinctShardBSI on a
Timestamp field, the request for a large enough pool of strings to hold
timestamp conversions of the nothing segfaults because r.Columns() on
a nil row segfaults.

To try to test this better, I added a filter to the executor test that
we use for this case, which got me a different result complaining about
a DistinctTimestamp result not being a SignedRow.

So, there's a couple of issues. One is that, in the case where a filter
is present, if the filter comes up with nothing, we can bail early
and return a result of the SignedRow type, which then breaks the reduce
part of our map/reduce when we try to reduce DistinctTimestamp values
into a SignedRow. To fix this, we make sure that we return the expected
type even in the case where we're bailing early.

A simpler way to see the actual original bug is, rather than having
a filter, just have a shard that has a value in *some other field*
but not in the timestamp field. So we add that to the test, too.

But also, really, since this is a problem that's happened more than
once, I propose that we also just make nil rows allow you to request
their columns and get back nil, so things like this don't bite us as
much. This wouldn't be a sufficient fix for the filter case, and I
still have the short-circuit for the nil row case explicitly in this
particular case because relying on the nil behavior bugs me, but I
think it's safer to allow .Columns on nil rows.
2022-02-16 16:52:00 -06:00
hphamMolecula
8f1349543f
Merge branch 'master' into sup-145 2022-02-14 14:40:12 -06:00
Hoang Pham
63b5eed010 SUP-145: Removed shard list in "shard unavailable" error log 2022-02-14 10:10:04 -06:00