Skip to content

Commit

Permalink
cli: Await pending async operations within command context
Browse files Browse the repository at this point in the history
Previously some NeoFS CLI commands like `container create` waited for
the operation persistence for a fixed period of time, decoupled from the
command timeout specified by `--timeout` flag. The wait process should
terminate when the command timeout expires.

Use command context as a waiting stop in contract write ops (`put`,
`delete`, `set-eacl`).

Closes nspcc-dev#2124.

Signed-off-by: Leonard Lyubich <leonard@morphbits.io>
  • Loading branch information
cthulhu-rider committed Jun 7, 2023
1 parent 78ae2f5 commit 27168de
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 21 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Changelog for NeoFS Node
### Changed
- NeoFS CLI generates random private key automatically if wallet is omitted (#2123)
- `morph.validators` config can be omitted for IR in local consensus mode but must be non-empty otherwise (#2311)
- NeoFS CLI `--timeout` flag limits whole command execution from now (#2124)

### Fixed
- Inability to restore RPC connection after the second disconnect (#2325)
Expand Down
22 changes: 14 additions & 8 deletions cmd/neofs-cli/modules/container/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,13 @@ It will be stored in sidechain when inner ring will accepts it.`,
key := key.Get(cmd)
cli := internalclient.GetSDKClientByFlag(cmd, key, commonflags.RPC)

ctx := cmd.Context()

if !force {
var prm internalclient.NetMapSnapshotPrm
prm.SetClient(cli)

resmap, err := internalclient.NetMapSnapshot(cmd.Context(), prm)
resmap, err := internalclient.NetMapSnapshot(ctx, prm)
common.ExitOnErr(cmd, "unable to get netmap snapshot to validate container placement, "+
"use --force option to skip this check: %w", err)

Expand Down Expand Up @@ -106,7 +108,7 @@ It will be stored in sidechain when inner ring will accepts it.`,
syncContainerPrm.SetClient(cli)
syncContainerPrm.SetContainer(&cnr)

_, err = internalclient.SyncContainerSettings(cmd.Context(), syncContainerPrm)
_, err = internalclient.SyncContainerSettings(ctx, syncContainerPrm)
common.ExitOnErr(cmd, "syncing container's settings rpc error: %w", err)

var putPrm internalclient.PutContainerPrm
Expand All @@ -117,7 +119,7 @@ It will be stored in sidechain when inner ring will accepts it.`,
putPrm.WithinSession(*tok)
}

res, err := internalclient.PutContainer(cmd.Context(), putPrm)
res, err := internalclient.PutContainer(ctx, putPrm)
common.ExitOnErr(cmd, "put container rpc error: %w", err)

id := res.ID()
Expand All @@ -131,17 +133,21 @@ It will be stored in sidechain when inner ring will accepts it.`,
getPrm.SetClient(cli)
getPrm.SetContainer(id)

for i := 0; i < awaitTimeout; i++ {
time.Sleep(1 * time.Second)
for {
time.Sleep(time.Second)

select {
case <-ctx.Done():
common.ExitOnErr(cmd, "", errCreateTimeout)
default:
}

_, err := internalclient.GetContainer(cmd.Context(), getPrm)
_, err := internalclient.GetContainer(ctx, getPrm)
if err == nil {
cmd.Println("container has been persisted on sidechain")
return
}
}

common.ExitOnErr(cmd, "", errCreateTimeout)
}
},
}
Expand Down
16 changes: 11 additions & 5 deletions cmd/neofs-cli/modules/container/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ Only owner of the container has a permission to remove container.`,
pk := key.Get(cmd)
cli := internalclient.GetSDKClientByFlag(cmd, pk, commonflags.RPC)

ctx := cmd.Context()

if force, _ := cmd.Flags().GetBool(commonflags.ForceFlag); !force {
common.PrintVerbose(cmd, "Reading the container to check ownership...")

Expand Down Expand Up @@ -92,7 +94,7 @@ Only owner of the container has a permission to remove container.`,
delPrm.WithinSession(*tok)
}

_, err := internalclient.DeleteContainer(cmd.Context(), delPrm)
_, err := internalclient.DeleteContainer(ctx, delPrm)
common.ExitOnErr(cmd, "rpc error: %w", err)

cmd.Println("container delete method invoked")
Expand All @@ -104,17 +106,21 @@ Only owner of the container has a permission to remove container.`,
getPrm.SetClient(cli)
getPrm.SetContainer(id)

for i := 0; i < awaitTimeout; i++ {
for {
time.Sleep(1 * time.Second)

_, err := internalclient.GetContainer(cmd.Context(), getPrm)
select {
case <-ctx.Done():
common.ExitOnErr(cmd, "", errDeleteTimeout)
default:
}

_, err := internalclient.GetContainer(ctx, getPrm)
if err != nil {
cmd.Println("container has been removed:", containerID)
return
}
}

common.ExitOnErr(cmd, "", errDeleteTimeout)
}
},
}
Expand Down
18 changes: 12 additions & 6 deletions cmd/neofs-cli/modules/container/set_eacl.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,12 @@ Container ID in EACL table will be substituted with ID from the CLI.`,
pk := key.GetOrGenerate(cmd)
cli := internalclient.GetSDKClientByFlag(cmd, pk, commonflags.RPC)

ctx := cmd.Context()

if !flagVarsSetEACL.noPreCheck {
cmd.Println("Checking the ability to modify access rights in the container...")

extendable, err := internalclient.IsACLExtendable(cmd.Context(), cli, id)
extendable, err := internalclient.IsACLExtendable(ctx, cli, id)
common.ExitOnErr(cmd, "Extensibility check failure: %w", err)

if !extendable {
Expand All @@ -55,7 +57,7 @@ Container ID in EACL table will be substituted with ID from the CLI.`,
setEACLPrm.WithinSession(*tok)
}

_, err := internalclient.SetEACL(cmd.Context(), setEACLPrm)
_, err := internalclient.SetEACL(ctx, setEACLPrm)
common.ExitOnErr(cmd, "rpc error: %w", err)

if containerAwait {
Expand All @@ -68,10 +70,16 @@ Container ID in EACL table will be substituted with ID from the CLI.`,
getEACLPrm.SetClient(cli)
getEACLPrm.SetContainer(id)

for i := 0; i < awaitTimeout; i++ {
for {
time.Sleep(1 * time.Second)

res, err := internalclient.EACL(cmd.Context(), getEACLPrm)
select {
case <-ctx.Done():
common.ExitOnErr(cmd, "", errSetEACLTimeout)
default:
}

res, err := internalclient.EACL(ctx, getEACLPrm)
if err == nil {
// compare binary values because EACL could have been set already
table := res.EACL()
Expand All @@ -86,8 +94,6 @@ Container ID in EACL table will be substituted with ID from the CLI.`,
}
}
}

common.ExitOnErr(cmd, "", errSetEACLTimeout)
}
},
}
Expand Down
2 changes: 0 additions & 2 deletions cmd/neofs-cli/modules/container/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ import (

const (
attributeDelimiter = "="

awaitTimeout = 120 // in seconds
)

var (
Expand Down

0 comments on commit 27168de

Please sign in to comment.