* deps: bump seaweedfs/raft so the leader quorum check follows the election timeout
A single master resuming raft state self-elects on a 1 ms election
timeout and restores the configured one afterwards, but the leader kept
running its quorum check every 1 ms for the rest of the process. The
raft change re-arms that check from the current timeout.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* deps: bump seaweedfs/raft to the raft PR head with the extended test
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* deps: bump seaweedfs/raft for the non-positive election timeout guard
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* deps: bump seaweedfs/raft so a timeout change re-arms the leader quorum check
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* deps: pin seaweedfs/raft v1.2.4
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* master: keep the hostname out of raft metric names
go-metrics prefixes gauge names with the hostname by default, which gives
every master its own metric family, e.g. SeaweedFS_<host>_raft_peers.
Prometheus already tells masters apart by the scrape target.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* master: send Hashicorp raft metrics through the go-metrics global raft uses
hashicorp/raft and raft-boltdb report through github.com/hashicorp/go-metrics,
but the master set up its prometheus sink on the armon/go-metrics global,
so a -raftHashicorp master exported no raft metric families. The sink is now
registered on the hashicorp/go-metrics global, and armon/go-metrics is no
longer a dependency.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* grafana: chart raft commit time and leader contact
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* grafana: keep the cluster in the raft panels
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* grafana: average raft commit time and leader contact over the rate window
The go-metrics summaries keep quantiles for 10s, so a p99 scraped every
30s misses most observations. The _sum/_count rates count every sample.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* grafana: leave raft panels empty when nothing was observed
Clamping the count rate plotted 0 ms for windows without commits.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* master: let the raft metrics test use its own registry
Registering on stats.Gather made go test -count=2 fail with a duplicate
collector registration.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* master: register raft metrics before opening the raft stores
raft.NewRaft starts its run loop before returning, so registering the
sink afterwards could drop the first state and boltdb samples.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* master: tell a warming-up Assign client when warm-up ends
During warm-up the master refuses Assign with Unavailable and now attaches
the remaining warm-up as a gRPC RetryInfo detail. RetryWithBackoff may
shorten a backoff step to that hint plus 50 ms, never lengthen it, and only
for a valid, positive hint, so a writer retries right after warm-up ends
instead of up to one backoff step later. The warm-up itself is unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* master: jitter the retry-hint slack and hint LookupVolume too
Per review: the slack added to a server hint is now random in
[50ms, 300ms], so clients refused at the same moment do not all retry
in one instant. The warm-up refusal of LookupVolume carries the same
RetryInfo hint as Assign; the masterclient's lookup retry already goes
through RetryWithBackoff, so it lands at warm-up end too.
Tests: the slow guard tests are replaced by one sleep-free table test
of the step logic (zero, negative, huge, malformed, valid and wrapped
hints, a hint longer than the step, none). One timing test of the
shortened step stays, plus a jitter-bounds test and a LookupVolume hint
test. The no-hint control test, which was timing-sensitive, is dropped.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* master: name the shared warm-up test and file the lookup test by topic
Rename the no-remaining test to TestWarmingUpErrorWithoutRemainingHasNoHint,
since the helper now serves Assign and LookupVolume, and move the
LookupVolume hint test next to the other LookupVolume warm-up tests.
Tests only.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* util: read the retry hint through ServerStatus
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* master: bound the warm-up hint in tests by the remaining warm-up around the RPC
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* test: leave more scheduler margin in the retry-hint timing tests
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* util, master: trim retry-hint comments
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* test: widen the retry-hint timing bounds to just under the unhinted wait
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* test: require a refused warm-up call before the hinted assign retry
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* test: check the hinted retry wait through a test timer, not the wall clock
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* test: move the assign warm-up end to 2.6s for more hinted-retry headroom
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* test: require the hinted retry to wait out its timer
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>
* deps: bump seaweedfs/raft for PreVote
The default raft gains the pre-vote phase so a master returning from a
partition can no longer depose a healthy leader with an inflated term.
Generated with [Devin](https://devin.ai)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* deps: bump seaweedfs/raft for pre-vote review follow-ups
Picks up the post-merge fixes on top of f227dce: per-round vote workers with per-peer dedupe, pre-vote grants counted at a newer term so mixed-version clusters cannot livelock, and state/conf field locking on the startup paths.
Generated with [Devin](https://devin.ai)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* deps: pin seaweedfs/raft to released v1.2.3
PreVote has merged and shipped as raft v1.2.3, so switch off the
PR-branch pseudo-version.
---------
Co-authored-by: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* iceberg maintenance: bound decimal, time, uuid, fixed and rescaled timestamp columns on compacted files
The column statistics written for a compacted data file give lower and upper
bounds only for booleans, integers, floats, dates, strings, binaries and
timestamps already stored in the Iceberg type's unit. Every other column is
left unbounded, so a reader can never skip a compacted file on it: a
DECIMAL(18,2) column written by DuckDB (stored as INT64) loses its bounds
after compaction, as does a millisecond timestamp, a TIME or a UUID.
boundLiteral now also converts:
- DECIMAL stored as INT32 or INT64 at the column's scale. A decimal stored
as a byte array still gets no bound: Parquet compares those statistics as
bytes, which does not order negative two's-complement values;
- TIME, TIMESTAMP, TIMESTAMPTZ and TIMESTAMP_NS from any Parquet time unit,
rescaled to the Iceberg unit; a value rescaled to a coarser unit is
rounded down for a lower bound and up for an upper bound so it stays a
bound, and a value that would overflow gets none;
- UUID and FIXED[n] from a FIXED_LEN_BYTE_ARRAY of the right length;
- a DOUBLE column read from a FLOAT file.
arrow-go becomes a direct dependency (decimal128, already in the module
graph through iceberg-go).
* iceberg maintenance: bound TIME(MILLIS) columns stored as INT32
* iceberg maintenance: bound timestamptz_ns columns too
---------
Co-authored-by: user.email <chrislusf@users.noreply.github.com>
The pinned dev snapshot (v1.85.0-dev.0.20260915183914) predates
grpc/grpc-go#9563, which fixes the control-buffer throttle deadlock
(grpc/grpc-go#9330) that wedges weed mini under concurrent S3 writes
over unix sockets.
Verified with the issue's standalone repro (one ClientConn over a unix
socket, concurrent unary RPCs): the old snapshot deadlocks at c=512
after 743 RPCs; the new snapshot completes 3.06M RPCs/20s at c=512 and
1.97M/15s at c=2048 with no stall -- above the v1.82.0 pre-regression
baseline of ~112k ops/s.
CI installs the templ CLI with `@latest`, which now generates code
calling templruntime.NewAttributeExpression — a symbol added after the
v0.3.1070 runtime pinned in go.mod, breaking `make install` builds on
clean runners. Bump the runtime to v0.3.1100 and regenerate.
Brings in the raft snapshot-recovery fixes: a recovered follower returns
to Follower so it can campaign when the leader goes away (masters on
ephemeral -mdir no longer wedge leaderless), and currentTerm stays
monotonic and persisted through recovery.
* build(deps): bump github.com/Azure/azure-sdk-for-go/sdk/storage/azblob
Bumps [github.com/Azure/azure-sdk-for-go/sdk/storage/azblob](https://github.com/Azure/azure-sdk-for-go) from 1.8.0 to 1.8.2.
- [Release notes](https://github.com/Azure/azure-sdk-for-go/releases)
- [Commits](https://github.com/Azure/azure-sdk-for-go/compare/sdk/azcore/v1.8.0...sdk/azidentity/v1.8.2)
---
updated-dependencies:
- dependency-name: github.com/Azure/azure-sdk-for-go/sdk/storage/azblob
dependency-version: 1.8.2
dependency-type: direct:production
update-type: version-update:semver-patch
...
Signed-off-by: dependabot[bot] <support@github.com>
* test: restore loadBucketMetadataFromFiler stub after TestGetBucketMetadata
TestGetBucketMetadata replaced the package-level loadBucketMetadataFromFiler
with a stub that sleeps one second per load and never restored it. Every
test running after it in the same binary paid that sleep on each bucket
metadata cache miss: TestPutObjectUploadACL (~245s) and
TestCopyObjectDestinationACL (~46s) each created a fresh BucketRegistry per
subtest, so the stub fired hundreds of times. In CI this stretched the
Test job past 11 minutes and left it exposed to runner cancellation.
Restore the real loader via t.Cleanup so the slow stub is scoped to the
test that needs it.
---------
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Chris Lu <chris.lu@gmail.com>
* deps: pin github.com/seaweedfs/goexif back to v1.0.3
The fork's newest tagged release is v1.0.3; the v2.0.0+incompatible
requirement resolved to older, untagged code and breaks isolated
builds that fetch it from the proxy.
Generated with [Devin](https://devin.ai)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* ci: stop dependabot bumping seaweedfs/goexif past its latest tag
Generated with [Devin](https://devin.ai)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* test/kafka: settle goexif at v1.0.3 too
The kafka test module recorded v2.0.0+incompatible in its own requires,
so MVS kept selecting it over the pinned v1.0.3 in the root module.
---------
Co-authored-by: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* build(deps): bump github.com/apache/iceberg-go
Bumps [github.com/apache/iceberg-go](https://github.com/apache/iceberg-go) from 0.6.1-0.20260817192109-c2105090c9e2 to 0.7.0.
- [Release notes](https://github.com/apache/iceberg-go/releases)
- [Commits](https://github.com/apache/iceberg-go/commits/v0.7.0)
---
updated-dependencies:
- dependency-name: github.com/apache/iceberg-go
dependency-version: 0.7.0
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot] <support@github.com>
* iceberg: write delete manifests with NewManifestWriter
iceberg-go 0.7.0 validates that delete entries only land in
delete-content manifests, so the WriteManifest + byte-level content
patch workaround no longer works: WriteManifest always creates a
data-content writer and rejects delete entries outright.
Use NewManifestWriter with WithManifestWriterContent instead and
dispatch entries through Add/Existing/Delete by status. The returned
ManifestFile now carries writer-computed counts, partitions and
min-sequence-number, so the manual ManifestFile rebuild is dropped.
---------
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Chris Lu <chris.lu@gmail.com>