120 lines
3.1 KiB
Go
120 lines
3.1 KiB
Go
package db
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"gestion/models"
|
|
"log"
|
|
"math"
|
|
)
|
|
|
|
// FindLeastLoadedDeliveryman trouve le livreur avec le moins de commandes ET qui peut accepter
|
|
func (d *Database) FindLeastLoadedDeliveryman() (string, error) {
|
|
keys, err := scanRedisKeys("delivery:status:*")
|
|
if err != nil || len(keys) == 0 {
|
|
return "", fmt.Errorf("aucun livreur trouvé")
|
|
}
|
|
|
|
var leastLoaded string
|
|
minQueueSize := int64(MAX_COMMANDS_PER_DELIVERYMAN + 1)
|
|
|
|
for _, key := range keys {
|
|
username := key[len("delivery:status:"):]
|
|
|
|
data, err := Redis.Get(RedisCtx, key).Result()
|
|
if err != nil {
|
|
continue
|
|
}
|
|
|
|
var status models.DeliveryPersonStatus
|
|
json.Unmarshal([]byte(data), &status)
|
|
|
|
if status.Status == "offline" {
|
|
continue
|
|
}
|
|
|
|
// ✅ NOUVEAU: Vérifier si le livreur peut accepter des commandes
|
|
if !d.CanDeliverymanAcceptCommands(username) {
|
|
log.Printf("⏭️ [LEAST_LOADED] Skip %s: ne peut pas accepter", username)
|
|
continue
|
|
}
|
|
|
|
queueKey := fmt.Sprintf("queue:deliveryman:%s", username)
|
|
queueSize, _ := Redis.ZCard(RedisCtx, queueKey).Result()
|
|
|
|
// Priorité aux livreurs disponibles (bonus de -1000)
|
|
effectiveQueueSize := queueSize
|
|
if status.Status == "available" {
|
|
effectiveQueueSize -= 1000
|
|
}
|
|
|
|
if effectiveQueueSize < minQueueSize {
|
|
minQueueSize = effectiveQueueSize
|
|
leastLoaded = username
|
|
}
|
|
}
|
|
|
|
if leastLoaded == "" {
|
|
return "", fmt.Errorf("aucun livreur disponible")
|
|
}
|
|
|
|
queueKey := fmt.Sprintf("queue:deliveryman:%s", leastLoaded)
|
|
actualQueueSize, _ := Redis.ZCard(RedisCtx, queueKey).Result()
|
|
|
|
log.Printf("🎯 [LEAST_LOADED] %s sélectionné (%d/10 commandes)",
|
|
leastLoaded, actualQueueSize)
|
|
|
|
return leastLoaded, nil
|
|
}
|
|
|
|
// GetLeastLoadedDeliverymanForced retourne le livreur avec le moins de commandes (SANS limite)
|
|
func (d *Database) GetLeastLoadedDeliverymanForced() (string, int64, error) {
|
|
activeUsernames, err := d.GetAllActiveDeliverymenUsernames()
|
|
if err != nil || len(activeUsernames) == 0 {
|
|
return "", 0, fmt.Errorf("aucun livreur actif")
|
|
}
|
|
|
|
var leastLoaded string
|
|
var minQueueSize int64 = math.MaxInt64
|
|
|
|
for _, username := range activeUsernames {
|
|
queueKey := fmt.Sprintf("queue:deliveryman:%s", username)
|
|
queueSize, _ := Redis.ZCard(RedisCtx, queueKey).Result()
|
|
|
|
if queueSize < minQueueSize {
|
|
minQueueSize = queueSize
|
|
leastLoaded = username
|
|
}
|
|
}
|
|
|
|
return leastLoaded, minQueueSize, nil
|
|
}
|
|
|
|
// AreAllDeliverymenAtCapacity vérifie si tous les livreurs ont atteint leur capacité max
|
|
func (d *Database) AreAllDeliverymenAtCapacity() (bool, int, error) {
|
|
activeUsernames, err := d.GetAllActiveDeliverymenUsernames()
|
|
if err != nil || len(activeUsernames) == 0 {
|
|
return false, 0, fmt.Errorf("aucun livreur actif")
|
|
}
|
|
|
|
if len(activeUsernames) == 1 {
|
|
return false, 1, nil
|
|
}
|
|
|
|
atCapacityCount := 0
|
|
for _, username := range activeUsernames {
|
|
if !d.CanDeliverymanAcceptCommands(username) {
|
|
atCapacityCount++
|
|
}
|
|
}
|
|
|
|
allAtCapacity := atCapacityCount == len(activeUsernames)
|
|
|
|
if allAtCapacity {
|
|
log.Printf("🔴 [CAPACITY] TOUS les livreurs sont à capacité maximale (%d/%d)",
|
|
atCapacityCount, len(activeUsernames))
|
|
}
|
|
|
|
return allAtCapacity, len(activeUsernames), nil
|
|
}
|