Skip to content

Reconciler configs are snapshotted at the start of each reconciliation#2009

Merged
knative-prow-robot merged 7 commits into
knative:masterfrom
dprotaso:reconcile-with-stable-configs
Sep 19, 2018
Merged

Reconciler configs are snapshotted at the start of each reconciliation#2009
knative-prow-robot merged 7 commits into
knative:masterfrom
dprotaso:reconcile-with-stable-configs

Conversation

@dprotaso
Copy link
Copy Markdown
Member

Currently, when reconciling a revision it's possible that when creating different dependent resources (ie. k8s services, kpa, deployments) different configuration values are read.

This race can be addressed by snapshotting the configs needed at the start of the reconciliation.

@knative-prow-robot knative-prow-robot added the size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. label Sep 12, 2018
@dprotaso
Copy link
Copy Markdown
Member Author

This will need to be done for other reconciler's

@dprotaso dprotaso force-pushed the reconcile-with-stable-configs branch from 293d83c to b28b3d1 Compare September 12, 2018 16:44
@dprotaso
Copy link
Copy Markdown
Member Author

/test pull-knative-serving-integration-tests

@dprotaso
Copy link
Copy Markdown
Member Author

/assign @tcnghia @mattmoor

@dprotaso dprotaso force-pushed the reconcile-with-stable-configs branch 4 times, most recently from 6ec9663 to 6b461cf Compare September 13, 2018 17:52
Copy link
Copy Markdown
Member

@mattmoor mattmoor left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did a pass over this, and left a handful of comments.

Generally, I think this is a net positive for the readability of the controller code, and would like to see us head more in this direction.

The use of reflection makes me a little uncomfortable about painful hard to debug bugs. I also left one comment about potentially making more direct use of Context.

I'd also suggest trying to break a couple pieces off of this that I think are separable and independently useful to distill this PR a bit.

Thanks!
-M

Comment thread pkg/reconciler/config/store.go Outdated
Comment thread pkg/reconciler/config/store.go Outdated
func NewUntypedStore(
name string,
logger Logger,
constructors ...interface{}) *UntypedStore {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reflection here makes me a bit uncomfortable, and I wonder if we can get close to this without it?

type CfgCtor func(...)...
type CfgCtors map[string]CfgCtor

func NewUntypedStore(
	name string,
	logger Logger,
	ctors CfgCtors) *UntypedStore {

The map enforces the argument pairing, and can be called with only slightly more code:

 _  = NewUntypedStore(name, logger, store.CfgCtors{
    "foo": fooCtor,
    "bar": barCtor,
})

There may be value in a map (e.g. explicit pairing, string is strongly typed) over the variadic convention even if the map's value has to be interface{} (I suspect at least some of the motivation for reflection is that Go doesn't allow[1] covariant return types?).

[1] - I was curious: golang/go#7512

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reflection here makes me a bit uncomfortable

It's solely needed for the constructor methods - not the keys

The map enforces the argument pairing, and can be called with only slightly more code:

Yeah I was optimizing for succinctness. Plus being comfortable with the non-idiomatic Go since it's pattern in Objective-C example

I'll switch to the map if that makes it clearer.

I suspect at least some of the motivation for reflection is that Go doesn't allow

Yup exactly - the typing is in go is very strict.

https://developer.apple.com/documentation/foundation/nsdictionary/1574181-dictionarywithobjectsandkeys

Comment thread pkg/reconciler/config/store.go Outdated
}

func (s *UntypedStore) registerConfig(name string, constructor interface{}) {
// TODO(dprotaso) assert constructor type
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like if this were possible we wouldn't need reflection (see my comment about covariant return types above).

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given the type system you cannot do this without reflection.

Comment thread hack/update-codegen.sh
Comment thread pkg/reconciler/testing/configmap.go Outdated
cfgs.Observability,
cfgs.Autoscaler,
cfgs.Controller,
)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(a train of thought)

My first thought here was:

Should we just pass cfgs?

However, that led me to wonder:

If we're just passing one additional thing, should we just pass ctx?

Which leads me to wonder:

Should we just be snapshotting individual configs to the context? Would that save us some code? Might there be ways to push config attachment to context into the common Reconciler infrastructure (like we have with the logger)?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we just pass cfgs?

In this specific example all configs are used so we could.

If we're just passing one additional thing, should we just pass ctx?

No - I'm wary of doing this because it makes inferring a function's actual arguments difficult

Passing a context.Context also signals that there's some 'cancelable' operation that might be occurring. So I wouldn't want to pass that to any of the resource.Make* methods.

Should we just be snapshotting individual configs to the context? Would that save us some code?

For the specific example above it would be more code since you'd load N configs from the context vs. one. It's something to consider

Might there be ways to push config attachment to context into the common Reconciler infrastructure (like we have with the logger)?

Maybe - baby steps first :)

@dprotaso dprotaso force-pushed the reconcile-with-stable-configs branch 2 times, most recently from 9ab66f8 to 9564e22 Compare September 18, 2018 18:40
@dprotaso dprotaso changed the title Revision reconciler's configs are snapshotted at the start of each reconciliation Reconciler configs are snapshotted at the start of each reconciliation Sep 18, 2018
@dprotaso dprotaso force-pushed the reconcile-with-stable-configs branch from 9564e22 to d9e1721 Compare September 18, 2018 20:30
@mattmoor
Copy link
Copy Markdown
Member

/lgtm
/approve
/hold

Can you doc comment the public parts of store.go?

@knative-prow-robot knative-prow-robot added lgtm Indicates that a PR is ready to be merged. do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. approved Indicates a PR has been approved by an approver from all required OWNERS files. labels Sep 18, 2018
@knative-prow-robot knative-prow-robot removed the lgtm Indicates that a PR is ready to be merged. label Sep 19, 2018
@knative-metrics-robot
Copy link
Copy Markdown

The following is the coverage report on pkg/.
Say /test pull-knative-serving-go-coverage to run the coverage report again

File Old Coverage New Coverage Delta
pkg/reconciler/config/store.go Do not exist 97.0%
pkg/reconciler/v1alpha1/revision/config/store.go Do not exist 100.0%
pkg/reconciler/v1alpha1/revision/cruds.go 98.2% 97.4% -0.8
pkg/reconciler/v1alpha1/revision/reconcile_resources.go 86.1% 86.3% 0.2
pkg/reconciler/v1alpha1/revision/revision.go 89.6% 96.3% 6.7
pkg/reconciler/v1alpha1/route/config/store.go Do not exist 100.0%
pkg/reconciler/v1alpha1/route/route.go 96.4% 96.1% -0.3

@dprotaso
Copy link
Copy Markdown
Member Author

godoc updated!

Copy link
Copy Markdown
Member

@mattmoor mattmoor left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/lgtm
/approve

Thanks @dprotaso

@knative-prow-robot knative-prow-robot added the lgtm Indicates that a PR is ready to be merged. label Sep 19, 2018
@knative-prow-robot
Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: dprotaso, mattmoor

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@mattmoor
Copy link
Copy Markdown
Member

/hold cancel

@knative-prow-robot knative-prow-robot removed the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Sep 19, 2018
@knative-prow-robot knative-prow-robot merged commit 0a8ada5 into knative:master Sep 19, 2018
@dprotaso dprotaso deleted the reconcile-with-stable-configs branch September 19, 2018 18:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files. lgtm Indicates that a PR is ready to be merged. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants