@@ -581,6 +581,73 @@ Then on the server side we:
581
581
3 . reject the request if waitUntilFreshAndBlock times out, thus forcing informers to retry.
582
582
4 . otherwise, construct the final list and send back to a client.
583
583
584
+ ### Replacing standard List request with WatchList mechanism for client-go's List method.
585
+
586
+ Replacing the underlying implementation of the List method for client-go based clients (like typed or dynamic client)
587
+ with the WatchList mechanism requires ensuring that the data returned by both the standard List request and
588
+ the new WatchList mechanism remains identical. The challenge is that WatchList no longer retrieves the entire
589
+ list from the server at once but only receives individual items, which forces us to "manually" reconstruct
590
+ the list object on the client side.
591
+
592
+ To correctly construct the list object on the client side, we need ListKind information.
593
+ However, simply reconstructing the list object based on these data is not enough.
594
+ In the case of a standard List request, the server's response (a versioned list) is processed through a chain of decoders,
595
+ which can potentially modify the resulting list object.
596
+ A good example is the WithoutVersionDecoder, which removes the GVK information from the list object.
597
+ Thus the "manually" constructed list object may not be consistent
598
+ with the transformations applied by the decoders, leading to differences.
599
+
600
+ To ensure full compatibility, the server must provide a versioned empty list in the format requested by the client (e.g., protobuf representation).
601
+ We don't know how the client's decoder behaves for different encodings, i.e., whether the decoder actually supports
602
+ the encoding we intend to use for reconstruction. Therefore, to ensure maximal compatibility, we will ensure that
603
+ the encoding used for the reconstruction of the list matches the format that the client originally requested.
604
+ This guarantees that the returned list object can be correctly decoded by the client,
605
+ preserving the actual encoding format as intended.
606
+
607
+ The proposed solution is to add a new annotation (` k8s.io/initial-events-list-blueprint ` ) to the object returned
608
+ in the bookmark event (The bookmark event is sent when the state is synced and marks the end of WatchList stream).
609
+ This annotation will store an empty, versioned list encoded as a Base64 string.
610
+ This annotation will be added to the same object/place the ` k8s.io/initial-events-end ` annotation is added.
611
+
612
+ When the client receives such a bookmark, it will base64 decode the empty list and pass it to the decoder chain.
613
+ Only after a successful response from the decoders the list will be populated with data received from subsequent
614
+ watch events and returned.
615
+
616
+ For example:
617
+ ```
618
+ GET /api/v1/namespaces/test/pods?watch=1&sendInitialEvents=true&allowWatchBookmarks=true&resourceVersion=&resourceVersionMatch=NotOlderThan
619
+ ---
620
+ 200 OK
621
+ Transfer-Encoding: chunked
622
+ Content-Type: application/json
623
+
624
+ {
625
+ "type": "ADDED",
626
+ "object": {"kind": "Pod", "apiVersion": "v1", "metadata": {"resourceVersion": "8467", "name": "foo"}, ...}
627
+ }
628
+ {
629
+ "type": "ADDED",
630
+ "object": {"kind": "Pod", "apiVersion": "v1", "metadata": {"resourceVersion": "5726", "name": "bar"}, ...}
631
+ }
632
+ {
633
+ "type":"BOOKMARK",
634
+ "object":{"kind":"Pod","apiVersion":"v1","metadata":{"resourceVersion":"13519","annotations":{"k8s.io/initial-events-end":"true","k8s.io/initial-events-embedded-list":"eyJraW5kIjoiUG9kTGlzdCIsImFwaVZlcnNpb24iOiJ2MSIsIm1ldGFkYXRhIjp7fSwiaXRlbXMiOm51bGx9Cg=="}} ...}
635
+ }
636
+ ...
637
+ <followed by regular watch stream starting>
638
+ ```
639
+
640
+ ## Alternatives
641
+
642
+ We could modify the type of the object passed in the last bookmark event to include the list.
643
+ This approach would require changes to the reflector, as it would need to recognize the new object type in the bookmark event.
644
+ However, this could potentially break other clients that are not expecting a different object in the bookmark event.
645
+
646
+ Another option would be to issue an empty list request to the API server to receive a list response from the client.
647
+ This approach would involve modifying client-go and implementing some form of caching mechanism,
648
+ possibly with invalidation policies.
649
+ Non-client-go clients that want to use this new feature would need to rebuild this mechanism as well.
650
+
584
651
### Test Plan
585
652
<!--
586
653
**Note:** *Not required until targeted at a release.*
0 commit comments