Skip to content
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

Handle component child / component dependent registration races when expanding deletion deps #7833

Open
pgavlin opened this issue Aug 24, 2021 · 1 comment · May be fixed by #7852
Open

Handle component child / component dependent registration races when expanding deletion deps #7833

pgavlin opened this issue Aug 24, 2021 · 1 comment · May be fixed by #7852
Assignees
Labels
customer/feedback Feedback from customers kind/bug Some behavior is incorrect or out of spec size/M Estimated effort to complete (up to 5 days).

Comments

@pgavlin
Copy link
Member

pgavlin commented Aug 24, 2021

See #7791 (comment) for details.

@pgavlin pgavlin added kind/bug Some behavior is incorrect or out of spec p1 Bugs severe enough to be the next item assigned to an engineer labels Aug 24, 2021
@pgavlin pgavlin added this to the 0.61 milestone Aug 24, 2021
@pgavlin pgavlin self-assigned this Aug 24, 2021
@emiliza emiliza added the customer/feedback Feedback from customers label Aug 24, 2021
pgavlin added a commit that referenced this issue Aug 26, 2021
Consider the following Pulumi program:

```typescript
class MyResource extends pulumi.CustomResource {
    // ...
}

class MyComponent extends pulumi.ComponentResource {
    constructor(name: string) {
        super("myComponent", name);

        this.child = new MyResource("child", {}, {parent: this});
    }
}

// Create a component resource. The constructor returns promptly, but
// the registration of the component itself happens asynchronously.
// Similarly, its child resource's constructor returns promptly, but
// its registration happens asynchronously. The SDK guarantees that the
// latter happens after the former by waiting on the parent's URN prior
// to registration (note that this is necessary in order for the runtime
// to fill out the `parent` field of the registration request).
const component = new MyComponent("component");

// Create a resource that depends on the component resource. The
// registration of this resource happens asynchronously, and races with
// the asynchronous registration of the component's child.
const res = new MyResource("resource", {}, {dependsOn: component});
```

Due to the races described in the comments, even when all of a
component's children are constructed prior to exiting the component's
constructor (e.g. not in applies, thens, etc.) we cannot guarantee that
the children have been registered prior to any resources that depend on
the component. Because of this, the approach that #7788 takes for
expanding dependencies on components to dependencies on their children
is not necessarily reliable, as it only adds children that appear prior
to dependents in the snapshot.

These changes adjust the dependency graph to add all children of a
component that would not create cycles in the dependency graph.

Fixes #7833.
@pgavlin pgavlin linked a pull request Aug 26, 2021 that will close this issue
pgavlin added a commit that referenced this issue Aug 26, 2021
Consider the following Pulumi program:

```typescript
class MyResource extends pulumi.CustomResource {
    // ...
}

class MyComponent extends pulumi.ComponentResource {
    constructor(name: string) {
        super("myComponent", name);

        this.child = new MyResource("child", {}, {parent: this});
    }
}

// Create a component resource. The constructor returns promptly, but
// the registration of the component itself happens asynchronously.
// Similarly, its child resource's constructor returns promptly, but
// its registration happens asynchronously. The SDK guarantees that the
// latter happens after the former by waiting on the parent's URN prior
// to registration (note that this is necessary in order for the runtime
// to fill out the `parent` field of the registration request).
const component = new MyComponent("component");

// Create a resource that depends on the component resource. The
// registration of this resource happens asynchronously, and races with
// the asynchronous registration of the component's child.
const res = new MyResource("resource", {}, {dependsOn: component});
```

Due to the races described in the comments, even when all of a
component's children are constructed prior to exiting the component's
constructor (e.g. not in applies, thens, etc.) we cannot guarantee that
the children have been registered prior to any resources that depend on
the component. Because of this, the approach that #7788 takes for
expanding dependencies on components to dependencies on their children
is not necessarily reliable, as it only adds children that appear prior
to dependents in the snapshot.

These changes adjust the dependency graph to add all children of a
component that would not create cycles in the dependency graph.

Fixes #7833.
pgavlin added a commit that referenced this issue Aug 26, 2021
Consider the following Pulumi program:

```typescript
class MyResource extends pulumi.CustomResource {
    // ...
}

class MyComponent extends pulumi.ComponentResource {
    constructor(name: string) {
        super("myComponent", name);

        this.child = new MyResource("child", {}, {parent: this});
    }
}

// Create a component resource. The constructor returns promptly, but
// the registration of the component itself happens asynchronously.
// Similarly, its child resource's constructor returns promptly, but
// its registration happens asynchronously. The SDK guarantees that the
// latter happens after the former by waiting on the parent's URN prior
// to registration (note that this is necessary in order for the runtime
// to fill out the `parent` field of the registration request).
const component = new MyComponent("component");

// Create a resource that depends on the component resource. The
// registration of this resource happens asynchronously, and races with
// the asynchronous registration of the component's child.
const res = new MyResource("resource", {}, {dependsOn: component});
```

Due to the races described in the comments, even when all of a
component's children are constructed prior to exiting the component's
constructor (e.g. not in applies, thens, etc.) we cannot guarantee that
the children have been registered prior to any resources that depend on
the component. Because of this, the approach that #7788 takes for
expanding dependencies on components to dependencies on their children
is not necessarily reliable, as it only adds children that appear prior
to dependents in the snapshot.

These changes adjust the dependency graph to add all children of a
component that would not create cycles in the dependency graph.

Fixes #7833.
@pgavlin
Copy link
Member Author

pgavlin commented Sep 10, 2021

A brief update: although this is certainly a problem that we need to fix, it is unlikely to trip in practice, and isn't quite as urgent as we had originally thought. In order for the ordering problems listed in this issue to arise, it must be possible for the registration of a component's children to race with the registration of a resource that depends on the component. While this is possible within the Pulumi model--particularly for in-process components--the existing implementations of Construct for MLCs prevent this from happening by waiting for all outstanding asynchronous work to finish before returning. That asynchronous work includes the registration of the component and its children, so dependents in other processes are unable to race as in the in-process case. So #7852 is still in progress, but has fallen a bit in priority.

@pgavlin pgavlin removed the p1 Bugs severe enough to be the next item assigned to an engineer label Sep 10, 2021
@emiliza emiliza modified the milestones: 0.61, 0.62 Sep 13, 2021
@emiliza emiliza added the size/M Estimated effort to complete (up to 5 days). label Sep 14, 2021
@emiliza emiliza removed this from the 0.62 milestone Oct 1, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
customer/feedback Feedback from customers kind/bug Some behavior is incorrect or out of spec size/M Estimated effort to complete (up to 5 days).
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants