Note: Feature requests are judged based on user experience and modeled on Go Experience Reports. These reports should focus on the problems: they should not focus on and need not propose solutions.
What you wanted to do
I want to run queries where individual traversals can be set with a timeout. This timeout can potentially trim the results of the query instead of returning all the data, but that’s OK. The use case has strict latency requirements and the query shouldn’t run longer than say 50ms.
What you actually did
Dgraph currently has query timeouts or cancellations. But this only returns a message saying the query was cancelled and does not returns any actual data of what it was able to process within the timeout.
Why that wasn’t great, with examples
One of the queries I want to run is a recursive query. It tries to go deep enough into the graph to return results. I want to be able to run a query where the query should stop after finding N connected nodes or if it hits a timeout.
One thing I can do today is run the recursive query multiple times with an increasing depth argument. But there’s no way to set a time limit while also getting a result if the time limit is reached.
We continue using the context library for timeouts but intercept the deadline exceeded errors and instead return whatever was retrieved by that point.
This approach seems easier to implement as it would not require changes to the parser or the query language. However, the disadvantages of these approach are that a lot of the error handling code would have to change and there’s the possibility that forgetting to handle those errors in some places would lead to the error bubbling up.
Implement this feature into the query language
Introducing a new directive @timelimit that can be set at any node in the query. The value passed to it would be the limit that processing that subgraph should take.
For example, the query in the previous post would look like.
Internally, the subgraphs would include the timelimit and a start date and compare the dates before doing anywork. If the maximum time has elapsed, an empty result is sent instead of a “deadline exceeded” error that propagates through the call stack.
Ideally, the directive can be included at any level of the graph. This requires that we define the behavior when a subgraph includes the directive and a parent of this subgraph includes a different value for it.
This option requires more changes but also is more flexible, as it allow us to have different limits for specific subgraphs and a similar mechanism could be use to expand to other types of limits.
Both solutions are a soft limit. In the case of the context based cancellation, the deadline is currently checked before doing the task. For the other approach, the check would also need to happen before. So it’s possible that queries run for longer if the last level of the graph takes more to process than the time left for processing.