Files
seaweedfs/weed/filer/etcd/etcd_store_kv.go
T
5a54009439 filer/etcd: client keepalive and per-request deadlines (#12621)
* filer/etcd: client keepalive and per-request deadlines

An etcd member that goes silent with its connections open (a dead or hung
node, a network partition, a frozen process) keeps the store's requests
balanced onto it waiting forever, because the client has no keepalive and
the calls have no deadline. Writes through the filer stop although the
other members keep quorum.

keepalive_timeout (default 3s, "0s" turns keepalive off) enables gRPC
keepalive with the ping interval fixed at gRPC's 10s minimum. gRPC also
sets TCP_USER_TIMEOUT to it on Linux, so a connection whose sent data goes
unacknowledged that long is closed by the kernel. request_timeout (default
3s) bounds every Get, Put and Delete unless the caller set a deadline;
timeout keeps its meaning as the dial timeout. DeleteFolderChildren gets no
request deadline: its DeleteRange grows with the directory, and keepalive
still ends it if the member goes silent.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Update weed/filer/etcd/etcd_store.go

Co-authored-by: Chris Lu <chrislusf@users.noreply.github.com>

* Update weed/filer/etcd/etcd_store_test.go

Co-authored-by: Chris Lu <chrislusf@users.noreply.github.com>

* Update weed/command/scaffold/filer.toml

Co-authored-by: Chris Lu <chrislusf@users.noreply.github.com>

* filer/etcd: no request deadline on entry writes

A Put whose client deadline expires may still have been committed. The
filer's upload handler treats the error as a failed write and deletes the
uploaded chunks, which the saved entry may then point at. InsertEntry and
UpdateEntry therefore keep the caller's context: etcd's own request
timeout ends a Put a live member cannot commit, and keepalive ends one on
a member that goes silent. Reads and deletes keep request_timeout; a
timed-out store delete returns before the filer deletes any chunks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* filer/etcd: no request deadline on KvPut

The filer wrapper stores a hard-linked file's attributes and chunk list
through KvPut. An HTTP append to a hard-linked file whose KvPut times out
after etcd saved it returns an error, and the upload handler deletes the
appended chunks the saved hard link now points at. KvPut keeps the
caller's context like InsertEntry and UpdateEntry.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Chris Lu <chrislusf@users.noreply.github.com>
2026-11-13 12:28:48 -08:00

53 lines
1.2 KiB
Go

package etcd
import (
"context"
"fmt"
"github.com/seaweedfs/seaweedfs/weed/filer"
)
// KvPut has no request deadline, like InsertEntry: the filer stores a hard-linked
// file's chunk list here, so a timed-out Put that was saved would leave it
// pointing at chunks the upload handler deletes.
func (store *EtcdStore) KvPut(ctx context.Context, key []byte, value []byte) (err error) {
_, err = store.client.Put(ctx, store.etcdKeyPrefix+string(key), string(value))
if err != nil {
return fmt.Errorf("kv put: %w", err)
}
return nil
}
func (store *EtcdStore) KvGet(ctx context.Context, key []byte) (value []byte, err error) {
opCtx, cancel := store.withTimeout(ctx)
defer cancel()
resp, err := store.client.Get(opCtx, store.etcdKeyPrefix+string(key), atScanRevision(ctx)...)
if err != nil {
return nil, fmt.Errorf("kv get: %w", err)
}
if len(resp.Kvs) == 0 {
return nil, filer.ErrKvNotFound
}
return resp.Kvs[0].Value, nil
}
func (store *EtcdStore) KvDelete(ctx context.Context, key []byte) (err error) {
opCtx, cancel := store.withTimeout(ctx)
defer cancel()
_, err = store.client.Delete(opCtx, store.etcdKeyPrefix+string(key))
if err != nil {
return fmt.Errorf("kv delete: %w", err)
}
return nil
}