diff --git a/service/client.go b/service/client.go index 6dc5355..b1a7f7d 100644 --- a/service/client.go +++ b/service/client.go @@ -596,6 +596,13 @@ func (s *ClientService) ResetClients(tx *gorm.DB, dt int64) ([]uint, error) { client.TotalDown += client.Down client.Up = 0 client.Down = 0 + changes = append(changes, model.Changes{ + DateTime: dt, + Actor: "ResetJob", + Key: "clients", + Action: "reset", + Obj: clientNameJSON(client.Name), + }) if !client.Enable { client.Enable = true var clientInboundIds []uint diff --git a/service/client_reset_test.go b/service/client_reset_test.go index c7e52f6..b5408c3 100644 --- a/service/client_reset_test.go +++ b/service/client_reset_test.go @@ -261,3 +261,41 @@ func TestResetUsageCountsTrafficArrivingWhileOpen(t *testing.T) { t.Errorf("totals = %d/%d, want 3500/9000", reset.TotalUp, reset.TotalDown) } } + +// A periodic reset that re-enables a depleted client must move LastUpdate, or +// the panel never reloads and keeps showing the client as disabled (#1287). +func TestPeriodicResetReenablesAndAnnounces(t *testing.T) { + db := clientTestDB(t) + s := &ClientService{} + + const now = int64(1_000_000) + c := createClient(t, db, &model.Client{ + Name: "depleted", + Enable: true, + AutoReset: true, + ResetDays: 30, + NextReset: now - 1, + Volume: 100, + Up: 200, + Inbounds: json.RawMessage(`[7]`), + }) + if err := db.Model(model.Client{}).Where("id = ?", c.Id).Update("enable", false).Error; err != nil { + t.Fatal(err) + } + LastUpdate = 0 + + ids, err := s.ResetClients(db, now) + if err != nil { + t.Fatal(err) + } + got := reload(t, db, c.Id) + if !got.Enable || got.Up != 0 { + t.Errorf("expected enabled with traffic reset, got enable=%v up=%d", got.Enable, got.Up) + } + if len(ids) != 1 || ids[0] != 7 { + t.Errorf("expected its inbound to be updated, got %v", ids) + } + if LastUpdate != now { + t.Errorf("LastUpdate = %d, want %d so the panel reloads", LastUpdate, now) + } +}