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

fix(service update): Retry an update in case of a conflict. #240

Merged
merged 2 commits into from
Jul 10, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions pkg/kn/commands/service/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ import (
"github.com/spf13/cobra"
)

const (
// How often to retry in case of an optimistic lock error when replacing a service (--force)
MaxUpdateRetries = 3
)

func NewServiceCommand(p *commands.KnParams) *cobra.Command {
serviceCmd := &cobra.Command{
Use: "service",
Expand Down
28 changes: 18 additions & 10 deletions pkg/kn/commands/service/service_create.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,17 +147,25 @@ func createService(client v1alpha1.KnClient, service *serving_v1alpha1_api.Servi
}

func replaceService(client v1alpha1.KnClient, service *serving_v1alpha1_api.Service, namespace string, out io.Writer) error {
existingService, err := client.GetService(service.Name)
if err != nil {
return err
}
service.ResourceVersion = existingService.ResourceVersion
err = client.UpdateService(service)
if err != nil {
return err
var retries = 0
for {
existingService, err := client.GetService(service.Name)
if err != nil {
return err
}
service.ResourceVersion = existingService.ResourceVersion
navidshaikh marked this conversation as resolved.
Show resolved Hide resolved
err = client.UpdateService(service)
if err != nil {
// Retry to update when a resource version conflict exists
if api_errors.IsConflict(err) && retries < MaxUpdateRetries {
navidshaikh marked this conversation as resolved.
Show resolved Hide resolved
retries++
continue
}
return err
}
fmt.Fprintf(out, "Service '%s' successfully replaced in namespace '%s'.\n", service.Name, namespace)
return nil
}
fmt.Fprintf(out, "Service '%s' successfully replaced in namespace '%s'.\n", service.Name, namespace)
return nil
}

func serviceExists(client v1alpha1.KnClient, name string, namespace string) (bool, error) {
Expand Down
41 changes: 25 additions & 16 deletions pkg/kn/commands/service/service_update.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@ import (
"errors"
"fmt"

"github.com/knative/client/pkg/kn/commands"
"github.com/spf13/cobra"
api_errors "k8s.io/apimachinery/pkg/api/errors"

"github.com/knative/client/pkg/kn/commands"
)

func NewServiceUpdateCommand(p *commands.KnParams) *cobra.Command {
Expand Down Expand Up @@ -52,24 +54,31 @@ func NewServiceUpdateCommand(p *commands.KnParams) *cobra.Command {
return err
}

service, err := client.GetService(args[0])
if err != nil {
return err
}
service = service.DeepCopy()
var retries = 0
for {
service, err := client.GetService(args[0])
if err != nil {
return err
}
service = service.DeepCopy()

Choose a reason for hiding this comment

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

i dont think we need DeepCopy

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not introduced in this PR, but happy to remove if safe. it was just my general understanding to copy objects before working on them to not compromise shared caches and other data structures which hold a reference.

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm with rhuss.


err = editFlags.Apply(service, cmd)
if err != nil {
return err
}
err = editFlags.Apply(service, cmd)
if err != nil {
return err
}

err = client.UpdateService(service)
if err != nil {
return err
err = client.UpdateService(service)
if err != nil {
// Retry to update when a resource version conflict exists
if api_errors.IsConflict(err) && retries < MaxUpdateRetries {
retries++
continue
}
return err
}
fmt.Fprintf(cmd.OutOrStdout(), "Service '%s' updated in namespace '%s'.\n", args[0], namespace)
return nil
}

fmt.Fprintf(cmd.OutOrStdout(), "Service '%s' updated in namespace '%s'.\n", args[0], namespace)
return nil
},
}

Expand Down