* feat: send EC shards in parallel per destination disk
One stream per destination disk. max_shard_transfers unset means no global cap, 0 sends shards sequentially, and N is a global cap that still keeps one stream per disk. The value is persisted through TaskPolicy. The maintenance form is a checkbox plus Max transfers because unset and 0 differ. The key is intentionally omitted from GetConfigSpec.
* ec shard distribution: treat negative max_shard_transfers as sequential
The config layer (normalizedMaxShardTransfers) clamps negative values to 0,
which selects sequential distribution. shardTransferCap diverged: a negative
cap that reached ShardDistributionOptions directly would have selected
uncapped parallel mode, the most aggressive setting. Align the options layer
with the same normalization so invalid input degrades to the conservative
mode.
* ec: serialize shard transfers to a server when a target leaves disk choice to the receiver
disk_id 0 is auto-placement on the receiving volume server, so an
auto-placed stream can land on a disk another queued stream is pinned
to. Grouping by (destNode, disk_id) alone let both run at once; collapse
all of that server's transfers under the destNode key instead.
* worker: clamp max_shard_transfers to the int32 wire range
ReadIntConfig returned the 0 fallback for values above MaxInt32, turning
a large positive cap into sequential mode. Read int64 and clamp into
range instead.
* worker: drop unused shard-transfer form helper
The maintenance form renders and collects max_shard_transfers in
plugin.templ JavaScript; the Go copy had no callers.
* worker: bound max_shard_transfers conversion under an in-range guard
---------
Co-authored-by: Chepurnov Simon <195125934+CHEPURNOV-S-S@users.noreply.github.com>
Co-authored-by: Chris Lu <chrislusf@users.noreply.github.com>
* admin: honor a persisted or admin.toml maintenance enabled=false
The startup path discarded an operator's enabled=false twice over:
ApplyDefaultsToProtobuf treated the bool zero value as unset and applied
the schema default of true, and a force-enable migration block flipped
any survivor. With the legacy /maintenance UI routes gone, nothing could
write the config either, so the maintenance system ran unconditionally.
Keep the persisted enabled flag across schema-default application in
LoadMaintenanceConfig, drop the force-enable block, and add a top-level
[maintenance] enabled key to admin.toml as the config surface, persisted
through SaveMaintenanceConfig like the per-task settings. Absent config
still defaults to enabled.
* admin: track presence on the maintenance enabled flag
A plain proto3 bool cannot distinguish an operator's persisted false
from a legacy file that simply omits the field, so honoring false would
have silently switched maintenance off for configs written before the
toggle could be persisted. Make the field optional: files that predate
presence tracking keep the enabled default, while a file that explicitly
persists the toggle is honored either way.
* fix(admin): implement ApplyPluginConfigFromToml to propagate settings to plugin config store
* Update weed/admin/dash/config_toml.go
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
* admin: overlay admin.toml onto plugin configs through bootstrap defaults
Creating a config from scratch at startup skipped the descriptor-defaults
bootstrap, so a job type with only worker keys in admin.toml persisted
Enabled=false and RetryLimit=0 and silently stopped running. Overlay
existing configs at startup, and apply the same overlay in
enrichConfigDefaults when the plugin bootstraps a fresh config from
descriptor defaults.
Also place collection_filter in the admin values where workers read it,
map preferred_tags as a string list, and stamp UpdatedAt.
* admin: trim the admin.toml help text and call-site comment
* admin: clamp toml retry values to the int32 range
* admin: fail startup when admin.toml cannot reach the plugin config
The legacy overlay already aborts startup when declared settings cannot
persist; continuing here would let workers bootstrap with stale values.
* admin: fix the retry clamp test on 32-bit
A 32-bit int cannot hold the oversized toml value, so viper returns 0
before the clamp runs.
---------
Co-authored-by: baracudaz <baracudaz@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: Chris Lu <chris.lu@gmail.com>
* admin: configure maintenance tasks via admin.toml
Maintenance task settings could only be edited in the admin UI and live
under <dataDir>/conf, so they silently reverted to defaults whenever the
data directory was recreated. An optional admin.toml now declares vacuum,
balance, and erasure coding settings; keys set there are written through
to the persisted task configs at every startup, overriding UI edits, so
the configuration stays declarative. Generate an example with
"weed scaffold -config=admin".
* vacuum: round min volume age up to whole hours
MinVolumeAgeSeconds was truncated by integer division when converted to
the hour-granular protobuf field, so a sub-hour setting silently became
0 and disabled the age guard.
* admin: split and normalize preferred_tags from admin.toml
A comma-separated string, as set via environment variable, came through
viper as a single slice element. Split on commas and reuse
util.NormalizeTagList, matching the plugin config path.
* scaffold: clarify admin.toml wording