[#2244] node: Update expired storage ID by WC

Previously, node could get an "infinite" small object: it could be expired
and thus could not be flushed (update its storage ID) to metabase => could
not be marked as flushed => node never removes such object and repeat all
the cycle one more time. If object exists and is not marked with GC (meta
returns `ErrObjectIsExpired`, not `ObjectNotFound` and not
`ObjectAlreadyRemoved`), its ID is safe to update _in the same_ bbolt
transaction.

Signed-off-by: Pavel Karpy <p.karpy@yadro.com>
This commit is contained in:
Pavel Karpy 2023-02-07 15:08:22 +03:00 committed by fyrchik
parent 351fdd9fa2
commit dbbbef9ddb
2 changed files with 7 additions and 3 deletions

View file

@ -35,6 +35,7 @@ Changelog for FrostFS Node
- `neofs-adm morph dump-hashes` now properly iterates over custom domain (#2224)
- Possible deadlock in write-cache (#2239)
- Fix `*_req_count` and `*_req_count_success` metric values (#2241)
- Storage ID update by write-cache (#2244)
### Removed
### Updated

View file

@ -1,6 +1,8 @@
package meta
import (
"errors"
oid "github.com/TrueCloudLab/frostfs-sdk-go/object/id"
"github.com/nspcc-dev/neo-go/pkg/util/slice"
"go.etcd.io/bbolt"
@ -94,10 +96,11 @@ func (db *DB) UpdateStorageID(prm UpdateStorageIDPrm) (res UpdateStorageIDRes, e
err = db.boltDB.Batch(func(tx *bbolt.Tx) error {
exists, err := db.exists(tx, prm.addr, currEpoch)
if !exists || err != nil {
return err
if err == nil && exists || errors.Is(err, ErrObjectIsExpired) {
err = updateStorageID(tx, prm.addr, prm.id)
}
return updateStorageID(tx, prm.addr, prm.id)
return err
})
return