> For the continuation token, I think one missing part is about the expiration > time of this token, since this may affect the state cleaning process of the > server.
Some storage services use a continuation token as a binary representation of internal states. For example, they serialize a structure into binary and then perform base64 encoding. Services don't need to maintain state, eliminating the need for state cleaning. > Do servers need to expose the expiration time to clients? If we choose to manage state on the server side, I recommend not revealing the expiration time to the client, at least not for now. We can introduce it when there's a practical need. It wouldn't constitute a breaking change, would it? On Wed, Dec 20, 2023, at 10:57, Renjie Liu wrote: > For the continuation token, I think one missing part is about the expiration > time of this token, since this may affect the state cleaning process of the > server. There are several things to discuss: > > 1. Should we leave it to the server to decide it or allow the client to > config in api? > > Personally I think it would be enough for the server to determine it for now, > since I don't see any usage to allow clients to set the expiration time in > api. > > 2. Do servers need to expose the expiration time to clients? > > Personally I think it would be enough to expose this through the getConfig > api to let users know this. For now there is no requirement for per request > expiration time. > > On Wed, Dec 20, 2023 at 2:49 AM Micah Kornfield <emkornfi...@gmail.com> wrote: >> IMO, parallelization needs to be a first class entity in the end >> point/service design to allow for flexibility (I scanned through the >> original proposal for the scan planning and it looked like it was on the >> right track). Using offsets for parallelization is problematic from both a >> consistency and scalability perspective if you want to allow for flexibility >> in implementation. >> >> In particular, I think the server needs an APIs like: >> >> DoScan - returns a list of partitions (represented by an opaque entity). >> The list of partitions should support pagination (in an ideal world, it >> would be streaming). >> GetTasksForPartition - Returns scan tasks for a partition (should also be >> paginated/streaming, but this is up for debate). I think it is an important >> consideration to allow for empty partitions. >> >> With this implementation you don't necessarily require separate server side >> state (objects in GCS should be sufficient), I think as Ryan suggested, one >> implementation could be to have each partition correspond to a byte-range in >> a manifest file for returning the tasks. >> >> Thanks, >> Micah >> >> >> >> On Tue, Dec 19, 2023 at 9:55 AM Walaa Eldin Moustafa <wa.moust...@gmail.com> >> wrote: >>> Not necessarily. That is more of a general statement. The pagination >>> discussion forked from server side scan planning. >>> >>> On Tue, Dec 19, 2023 at 9:52 AM Ryan Blue <b...@tabular.io> wrote: >>>> > With start/limit each client can query for own's chunk without >>>> > coordination. >>>> >>>> Okay, I understand now. Would you need to parallelize the client for >>>> listing namespaces or tables? That seems odd to me. >>>> >>>> On Tue, Dec 19, 2023 at 9:48 AM Walaa Eldin Moustafa >>>> <wa.moust...@gmail.com> wrote: >>>>> > You can parallelize with opaque tokens by sending a starting point for >>>>> > the next request. >>>>> >>>>> I meant we would have to wait for the server to return this starting >>>>> point from the past request? With start/limit each client can query for >>>>> own's chunk without coordination. >>>>> >>>>> >>>>> On Tue, Dec 19, 2023 at 9:44 AM Ryan Blue <b...@tabular.io> wrote: >>>>>> > I think start and offset has the advantage of being parallelizable (as >>>>>> > compared to continuation tokens). >>>>>> >>>>>> You can parallelize with opaque tokens by sending a starting point for >>>>>> the next request. >>>>>> >>>>>> > On the other hand, using "asOf" can be complex to implement and may >>>>>> > be too powerful for the pagination use case >>>>>> >>>>>> I don't think that we want to add `asOf`. If the service chooses to do >>>>>> this, it would send a continuation token that has the information >>>>>> embedded. >>>>>> >>>>>> On Tue, Dec 19, 2023 at 9:42 AM Walaa Eldin Moustafa >>>>>> <wa.moust...@gmail.com> wrote: >>>>>>> Can we assume it is the responsibility of the server to ensure >>>>>>> determinism (e.g., by caching the results along with query ID)? I think >>>>>>> start and offset has the advantage of being parallelizable (as compared >>>>>>> to continuation tokens). On the other hand, using "asOf" can be complex >>>>>>> to implement and may be too powerful for the pagination use case >>>>>>> (because it allows to query the warehouse as of any point of time, not >>>>>>> just now). >>>>>>> >>>>>>> Thanks, >>>>>>> Walaa. >>>>>>> >>>>>>> On Tue, Dec 19, 2023 at 9:40 AM Ryan Blue <b...@tabular.io> wrote: >>>>>>>> I think you can solve the atomicity problem with a continuation token >>>>>>>> and server-side state. In general, I don't think this is a problem we >>>>>>>> should worry about a lot since pagination commonly has this problem. >>>>>>>> But since we can build a system that allows you to solve it if you >>>>>>>> choose to, we should go with that design. >>>>>>>> >>>>>>>> On Tue, Dec 19, 2023 at 9:13 AM Micah Kornfield >>>>>>>> <emkornfi...@gmail.com> wrote: >>>>>>>>> Hi Jack, >>>>>>>>> Some answers inline. >>>>>>>>> >>>>>>>>>> In addition to the start index approach, another potential simple >>>>>>>>>> way to implement the continuation token is to use the last item >>>>>>>>>> name, when the listing is guaranteed to be in lexicographic order. >>>>>>>>> >>>>>>>>> I think this is one viable implementation, but the reason that the >>>>>>>>> token should be opaque is that it allows several different >>>>>>>>> implementations without client side changes. >>>>>>>>> >>>>>>>>>> For example, if an element is added before the continuation token, >>>>>>>>>> then all future listing calls with the token would always skip that >>>>>>>>>> element. >>>>>>>>> >>>>>>>>> IMO, I think this is fine, for some of the REST APIs it is likely >>>>>>>>> important to put constraints on atomicity requirements, for others >>>>>>>>> (e.g. list namespaces) I think it is OK to have looser requirements. >>>>>>>>> >>>>>>>>>> If we want to enforce that level of atomicity, we probably want to >>>>>>>>>> introduce another time travel query parameter (e.g. >>>>>>>>>> asOf=1703003028000) to ensure that we are listing results at a >>>>>>>>>> specific point of time of the warehouse, so the complete result list >>>>>>>>>> is fixed. >>>>>>>>> >>>>>>>>> Time travel might be useful in some cases but I think it is >>>>>>>>> orthogonal to services wishing to have guarantees around >>>>>>>>> atomicity/consistency of results. If a server wants to ensure that >>>>>>>>> results are atomic/consistent as of the start of the listing, it can >>>>>>>>> embed the necessary timestamp in the token it returns and parse it >>>>>>>>> out when fetching the next result. >>>>>>>>> >>>>>>>>> I think this does raise a more general point around service >>>>>>>>> definition evolution in general. I think there likely need to be >>>>>>>>> metadata endpoints that expose either: >>>>>>>>> 1. A version of the REST API supported. >>>>>>>>> 2. Features the API supports (e.g. which query parameters are >>>>>>>>> honored for a specific endpoint). >>>>>>>>> >>>>>>>>> There are pros and cons to both approaches (apologies if I missed >>>>>>>>> this in the spec or if it has already been discussed). >>>>>>>>> >>>>>>>>> Cheers, >>>>>>>>> Micah >>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>> On Tue, Dec 19, 2023 at 8:25 AM Jack Ye <yezhao...@gmail.com> wrote: >>>>>>>>>> Yes I agree that it is better to not enforce the implementation to >>>>>>>>>> favor any direction, and continuation token is probably better than >>>>>>>>>> enforcing a numeric start index. >>>>>>>>>> >>>>>>>>>> In addition to the start index approach, another potential simple >>>>>>>>>> way to implement the continuation token is to use the last item >>>>>>>>>> name, when the listing is guaranteed to be in lexicographic order. >>>>>>>>>> Compared to the start index approach, it does not need to worry >>>>>>>>>> about the change of start index when something in the list is added >>>>>>>>>> or removed. >>>>>>>>>> >>>>>>>>>> However, the issue of concurrent modification could still exist even >>>>>>>>>> with a continuation token. For example, if an element is added >>>>>>>>>> before the continuation token, then all future listing calls with >>>>>>>>>> the token would always skip that element. If we want to enforce that >>>>>>>>>> level of atomicity, we probably want to introduce another time >>>>>>>>>> travel query parameter (e.g. asOf=1703003028000) to ensure that we >>>>>>>>>> are listing results at a specific point of time of the warehouse, so >>>>>>>>>> the complete result list is fixed. (This is also the missing piece I >>>>>>>>>> forgot to mention in the start index approach to ensure it works in >>>>>>>>>> distributed settings) >>>>>>>>>> >>>>>>>>>> -Jack >>>>>>>>>> >>>>>>>>>> On Tue, Dec 19, 2023, 9:51 AM Micah Kornfield >>>>>>>>>> <emkornfi...@gmail.com> wrote: >>>>>>>>>>> I tried to cover these in more details at: >>>>>>>>>>> https://docs.google.com/document/d/1bbfoLssY1szCO_Hm3_93ZcN0UAMpf7kjmpwHQngqQJ0/edit >>>>>>>>>>> >>>>>>>>>>> On Sun, Dec 17, 2023 at 6:07 PM Renjie Liu >>>>>>>>>>> <liurenjie2...@gmail.com> wrote: >>>>>>>>>>>> +1 for this approach. I agree that the streaming approach requires >>>>>>>>>>>> that http client and servers have http 2 streaming support, which >>>>>>>>>>>> is not compatible with old clients. >>>>>>>>>>>> >>>>>>>>>>>> I share the same concern with Micah that only start/limit may not >>>>>>>>>>>> be enough in a distributed environment where modification happens >>>>>>>>>>>> during iterations. For compatibility, we need to consider several >>>>>>>>>>>> cases: >>>>>>>>>>>> >>>>>>>>>>>> 1. Old client <-> New Server >>>>>>>>>>>> 2. New client <-> Old server >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> On Sat, Dec 16, 2023 at 6:51 AM Daniel Weeks <dwe...@apache.org> >>>>>>>>>>>> wrote: >>>>>>>>>>>>> I agree that we want to include this feature and I raised similar >>>>>>>>>>>>> concerns to what Micah already presented in talking with Ryan. >>>>>>>>>>>>> >>>>>>>>>>>>> For backward compatibility, just adding a start and limit implies >>>>>>>>>>>>> a deterministic order, which is not a current requirement of the >>>>>>>>>>>>> REST spec. >>>>>>>>>>>>> >>>>>>>>>>>>> Also, we need to consider whether the start/limit would need to >>>>>>>>>>>>> be respected by the server. If existing implementations simply >>>>>>>>>>>>> return all the results, will that be sufficient? There are a few >>>>>>>>>>>>> edge cases that need to be considered here. >>>>>>>>>>>>> >>>>>>>>>>>>> For the opaque key approach, I think adding a query param to >>>>>>>>>>>>> trigger/continue and introducing a continuation token in the >>>>>>>>>>>>> ListNamespacesResponse might allow for more backward >>>>>>>>>>>>> compatibility. In that scenario, pagination would only take >>>>>>>>>>>>> place for clients who know how to paginate and the ordering would >>>>>>>>>>>>> not need to be deterministic. >>>>>>>>>>>>> >>>>>>>>>>>>> -Dan >>>>>>>>>>>>> >>>>>>>>>>>>> On Fri, Dec 15, 2023, 10:33 AM Micah Kornfield >>>>>>>>>>>>> <emkornfi...@gmail.com> wrote: >>>>>>>>>>>>>> Just to clarify and add a small suggestion: >>>>>>>>>>>>>> >>>>>>>>>>>>>> The behavior with no additional parameters requires the >>>>>>>>>>>>>> operations to happen as they do today for backwards >>>>>>>>>>>>>> compatibility (i.e either all responses are returned or a >>>>>>>>>>>>>> failure occurs). >>>>>>>>>>>>>> >>>>>>>>>>>>>> For new parameters, I'd suggest an opaque start token (instead >>>>>>>>>>>>>> of specific numeric offset) that can be returned by the service >>>>>>>>>>>>>> and a limit (as proposed above). If a start token is provided >>>>>>>>>>>>>> without a limit a default limit can be chosen by the server. >>>>>>>>>>>>>> Servers might return less than limit (i.e. clients are required >>>>>>>>>>>>>> to check for a next token to determine if iteration is >>>>>>>>>>>>>> complete). This enables server side state if it is desired but >>>>>>>>>>>>>> also makes deterministic listing much more feasible >>>>>>>>>>>>>> (deterministic responses are essentially impossible in the face >>>>>>>>>>>>>> of changing data if only a start offset is provided). >>>>>>>>>>>>>> >>>>>>>>>>>>>> In an ideal world, specifying a limit would result in streaming >>>>>>>>>>>>>> responses being returned with the last part either containing a >>>>>>>>>>>>>> token if continuation is necessary. Given conversation on the >>>>>>>>>>>>>> other thread of streaming, I'd imagine this is quite hard to >>>>>>>>>>>>>> model in an Open API REST service. >>>>>>>>>>>>>> >>>>>>>>>>>>>> Therefore it seems like using pagination with token and offset >>>>>>>>>>>>>> would be preferred. If skipping someplace in the middle of the >>>>>>>>>>>>>> namespaces is required then I would suggest modelling those as >>>>>>>>>>>>>> first class query parameters (e.g. "startAfterNamespace") >>>>>>>>>>>>>> >>>>>>>>>>>>>> Cheers, >>>>>>>>>>>>>> Micah >>>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>>> On Fri, Dec 15, 2023 at 10:08 AM Ryan Blue <b...@tabular.io> >>>>>>>>>>>>>> wrote: >>>>>>>>>>>>>>> +1 for this approach >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> I think it's good to use query params because it can be >>>>>>>>>>>>>>> backward-compatible with the current behavior. If you get more >>>>>>>>>>>>>>> than the limit back, then the service probably doesn't support >>>>>>>>>>>>>>> pagination. And if a client doesn't support pagination they get >>>>>>>>>>>>>>> the same results that they would today. A streaming approach >>>>>>>>>>>>>>> with a continuation link like in the scan API discussion >>>>>>>>>>>>>>> wouldn't work because old clients don't know to make a second >>>>>>>>>>>>>>> request. >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> On Thu, Dec 14, 2023 at 10:07 AM Jack Ye <yezhao...@gmail.com> >>>>>>>>>>>>>>> wrote: >>>>>>>>>>>>>>>> Hi everyone, >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> During the conversation of the Scan API for REST spec, we >>>>>>>>>>>>>>>> touched on the topic of pagination when REST response is large >>>>>>>>>>>>>>>> or takes time to be produced. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> I just want to discuss this separately, since we also see the >>>>>>>>>>>>>>>> issue for ListNamespaces and ListTables/Views, when >>>>>>>>>>>>>>>> integrating with a large organization that has over 100k >>>>>>>>>>>>>>>> namespaces, and also a lot of tables in some namespaces. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> Pagination requires either keeping state, or the response to >>>>>>>>>>>>>>>> be deterministic such that the client can request a range of >>>>>>>>>>>>>>>> the full response. If we want to avoid keeping state, I think >>>>>>>>>>>>>>>> we need to allow some query parameters like: >>>>>>>>>>>>>>>> - *start*: the start index of the item in the response >>>>>>>>>>>>>>>> - *limit*: the number of items to be returned in the response >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> So we can send a request like: >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> *GET /namespaces?start=300&limit=100* >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> *GET /namespaces/ns/tables?start=300&limit=100* >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> And the REST spec should enforce that the response returned >>>>>>>>>>>>>>>> for the paginated GET should be deterministic. >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> Any thoughts on this? >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> Best, >>>>>>>>>>>>>>>> Jack Ye >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> -- >>>>>>>>>>>>>>> Ryan Blue >>>>>>>>>>>>>>> Tabular >>>>>>>> >>>>>>>> >>>>>>>> -- >>>>>>>> Ryan Blue >>>>>>>> Tabular >>>>>> >>>>>> >>>>>> -- >>>>>> Ryan Blue >>>>>> Tabular >>>> >>>> >>>> -- >>>> Ryan Blue >>>> Tabular Xuanwo