-
-
Notifications
You must be signed in to change notification settings - Fork 326
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Align watcher::Event
init/page variants
#1504
Conversation
**Merges - `Event::InitPage` and `Event::InitApply`** This has several consequences; - buffering of pages done in watcher (need to benchmark this since it is likely worse memory wise) - no buffering needed in any flatteners (further simplification can be done later) Signed-off-by: clux <[email protected]>
watcher::Event
variants for initialisationwatcher::Event
init/page variants
Signed-off-by: clux <[email protected]>
Signed-off-by: clux <[email protected]>
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #1504 +/- ##
=======================================
+ Coverage 75.0% 75.1% +0.2%
=======================================
Files 78 78
Lines 6854 6864 +10
=======================================
+ Hits 5134 5150 +16
+ Misses 1720 1714 -6
|
Signed-off-by: clux <[email protected]>
Quick controller deployment of gives me the exact same memory profile as the one with zero buffering, so this appears to be a pure ergonomic improvement. |
Signed-off-by: clux <[email protected]>
Signed-off-by: clux <[email protected]>
Signed-off-by: clux <[email protected]>
// We're filtering by object name, so getting more than one object means that either: | ||
// 1. The apiserver is accepting multiple objects with the same name, or | ||
// 2. The apiserver is ignoring our query | ||
// In either case, the K8s apiserver is broken and our API will return invalid data, so | ||
// we had better bail out ASAP. | ||
Ok(Event::InitPage(objs)) if objs.len() > 1 => Some(Err(Error::TooManyObjects)), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NB: This comment was technically wrong because it can happen if users use a Api::all
scoped Api
against names that exist in multiple namespaces. Now we just pick the first consistently (which is also what we did for streaming lists).
Additionally because page events do not happen anymore, the TooManyObjects
error goes away (this is the only real place it happened). Tests have used this error variant everywhere as a type of convenience though, so that's why there's many strange test changes touching this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, that explains the tests... is the ordering random or does the api server ever pre-filter the objects based on some other property like timestamp (i.e. creation time)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i think on a watch against rv="0" it's actually alphabetical - which in this case doesn't help much if there's duplicate objects (in say different namespaces).
bad idea
it's possible we could change this fn to split depending on what scope the `Api` is used for, ala:
let fields = if let Some(ns) = api.namespace {
format!("metadata.name={name},metadata.namespace={ns}")
} else {
format!("metadata.name={name}")
};
but that requires exposing namespace as pub, so will do that as a follow-up
EDIT: it also doesn't help because if the Api
(being passed in` is scoped to namespace, then the watch is also scoped so this suggestion is pointless.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
minor docs follow-up for this: #1510
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great! Thanks so much for the clean-up and really straightforward comments, it made reviewing much easier.
Self { | ||
stream, | ||
queue: vec![].into_iter(), | ||
emit_deleted, | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
kind of cool that this got simplified as a result
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, think we can maybe deprecate / repurpose this thing entirely to some kind of filter module instead (since the concept of an "unflattened stream" kind of goes away externally (which is good, it was a big source of confusion).
} | ||
InitialListStrategy::ListWatch => (Some(Ok(Event::Init)), State::InitPage { | ||
continue_token: None, | ||
objects: VecDeque::default(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we know the page size in advance (since it's part of the strategy) would it make sense to allocate a ring buffer with a predetermined capacity equal to the page size? Bit of a micro optimisation I suppose 🤔
Edit: nvm, this wouldn't work since we always construct a new InitPage
for each page we consume. Would overcomplicate things.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hm, yeah, maybe there is something we can do here, but not sure what. it's also going to become "the old way" of doing things once this kubernetes feature becomes stabilised and rolled out everywhere, so 🤷
it doesn't seem to perform any noticeably worse than with main
(with the zero buffering in watcher setup) so it's probably fine. have run this for a week now.
// We're filtering by object name, so getting more than one object means that either: | ||
// 1. The apiserver is accepting multiple objects with the same name, or | ||
// 2. The apiserver is ignoring our query | ||
// In either case, the K8s apiserver is broken and our API will return invalid data, so | ||
// we had better bail out ASAP. | ||
Ok(Event::InitPage(objs)) if objs.len() > 1 => Some(Err(Error::TooManyObjects)), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, that explains the tests... is the ordering random or does the api server ever pre-filter the objects based on some other property like timestamp (i.e. creation time)?
and two other minor ones Signed-off-by: clux <[email protected]>
Merges -
Event::InitPage
intoEvent::InitApply
Follow-up to the unreleased #1494 as suggested in #1499.
This has several consequences;
Event
enum if we remove paging (when streaming lists is stabilised and everywhere)Because of 1. this slightly changing the no-buffering PR in #1494 and as such it needs to be benchmarked, but it is a nice reduction in complexity within the runtime if we can justify it. EDIT: it performs the same.
The second point kind of hints at an even larger refactoring where we do not pass vector around internally at all and possibly killing/repurposing
EventFlatten
.