This commit is contained in:
2026-09-22 15:27:13 +05:30
parent 29e189b7e0
commit ee79c80338
8 changed files with 1042 additions and 4 deletions

View File

@@ -140,7 +140,12 @@ func collectEligibleCandidates(nearby []redis.GeoLocation) ([]*milerCandidate, [
continue
}
if profile.Availabilitystatus != constants.MilerAvailable {
// Carrying an order is not a reason to be skipped — maxActive below
// is what decides how much one miler can hold. Testing for Available
// here made that cap unreachable: a rider was eligible only while
// idle, so activeCount was always 0 and the multi-stop round the cap
// was written for could never be built.
if !constants.MilerCanTakeWork(profile.Availabilitystatus) {
continue
}
@@ -152,7 +157,7 @@ func collectEligibleCandidates(nearby []redis.GeoLocation) ([]*milerCandidate, [
}).
Count(&activeCount)
if activeCount >= maxActive {
if activeCount >= maxActiveBookings() {
continue
}

View File

@@ -4,6 +4,9 @@ import (
"context"
"encoding/json"
"fmt"
"os"
"strconv"
"strings"
"time"
"doormile/constants"
@@ -21,9 +24,28 @@ const (
retryDelay = 2 * time.Minute
geoRadiusKm = 10.0
geoMaxCount = 10
maxActive = 3
// defaultMaxActive is how many open stops one miler may hold at once.
// Override with MILER_MAX_ACTIVE_BOOKINGS — how many parcels a rider can
// realistically run in one round is an operational call, not a constant,
// and it differs between a dense city round and an intercity leg.
defaultMaxActive = 3
)
// maxActiveBookings reads the per-miler concurrent-stop cap, read per call so
// it can be changed without a redeploy. A non-numeric or non-positive value
// falls back to the default rather than uncapping the fleet by typo.
func maxActiveBookings() int64 {
if v := strings.TrimSpace(os.Getenv("MILER_MAX_ACTIVE_BOOKINGS")); v != "" {
if n, err := strconv.Atoi(v); err == nil && n > 0 {
return int64(n)
}
utils.Warn("MILER_MAX_ACTIVE_BOOKINGS is not a positive integer, using the default",
"value", v, "default", defaultMaxActive)
}
return defaultMaxActive
}
type milerCandidate struct {
profile models.MilerProfile
distanceKm float64

View File

@@ -0,0 +1,32 @@
package assignment
import "testing"
// The per-miler concurrent-stop cap.
//
// This is the knob that now decides how much one rider carries, because
// eligibility no longer stops at the first order. It is read per call so it
// can be changed without a redeploy — and a typo must never uncap the fleet.
func TestMaxActiveBookings(t *testing.T) {
cases := []struct {
env string
want int64
why string
}{
{"", defaultMaxActive, "unset falls back to the default"},
{"10", 10, "a plain number is honoured"},
{" 8 ", 8, "surrounding whitespace is tolerated"},
{"1", 1, "one stop at a time is a legitimate policy"},
{"0", defaultMaxActive, "zero would assign to nobody — treated as unset, not as a cap"},
{"-4", defaultMaxActive, "negative is meaningless here"},
{"lots", defaultMaxActive, "a typo must not uncap the fleet"},
{"3.5", defaultMaxActive, "not an integer"},
}
for _, tc := range cases {
t.Setenv("MILER_MAX_ACTIVE_BOOKINGS", tc.env)
if got := maxActiveBookings(); got != tc.want {
t.Errorf("MILER_MAX_ACTIVE_BOOKINGS=%q gave %d, want %d (%s)", tc.env, got, tc.want, tc.why)
}
}
}