| 436 | ) |
| 437 | |
| 438 | func (h *Handler) gcCache() { |
| 439 | if h.gcing.Load() { |
| 440 | return |
| 441 | } |
| 442 | if !h.gcing.CompareAndSwap(false, true) { |
| 443 | return |
| 444 | } |
| 445 | defer h.gcing.Store(false) |
| 446 | |
| 447 | if time.Since(h.gcAt) < time.Hour { |
| 448 | h.logger.Debugf("skip gc: %v", h.gcAt.String()) |
| 449 | return |
| 450 | } |
| 451 | h.gcAt = time.Now() |
| 452 | h.logger.Debugf("gc: %v", h.gcAt.String()) |
| 453 | |
| 454 | db, err := h.openDB() |
| 455 | if err != nil { |
| 456 | return |
| 457 | } |
| 458 | defer db.Close() |
| 459 | |
| 460 | // Remove the caches which are not completed for a while, they are most likely to be broken. |
| 461 | var caches []*Cache |
| 462 | if err := db.Find(&caches, bolthold. |
| 463 | Where("UsedAt").Lt(time.Now().Add(-keepTemp).Unix()). |
| 464 | And("Complete").Eq(false), |
| 465 | ); err != nil { |
| 466 | h.logger.Warnf("find caches: %v", err) |
| 467 | } else { |
| 468 | for _, cache := range caches { |
| 469 | h.storage.Remove(cache.ID) |
| 470 | if err := db.Delete(cache.ID, cache); err != nil { |
| 471 | h.logger.Warnf("delete cache: %v", err) |
| 472 | continue |
| 473 | } |
| 474 | h.logger.Infof("deleted cache: %+v", cache) |
| 475 | } |
| 476 | } |
| 477 | |
| 478 | // Remove the old caches which have not been used recently. |
| 479 | caches = caches[:0] |
| 480 | if err := db.Find(&caches, bolthold. |
| 481 | Where("UsedAt").Lt(time.Now().Add(-keepUnused).Unix()), |
| 482 | ); err != nil { |
| 483 | h.logger.Warnf("find caches: %v", err) |
| 484 | } else { |
| 485 | for _, cache := range caches { |
| 486 | h.storage.Remove(cache.ID) |
| 487 | if err := db.Delete(cache.ID, cache); err != nil { |
| 488 | h.logger.Warnf("delete cache: %v", err) |
| 489 | continue |
| 490 | } |
| 491 | h.logger.Infof("deleted cache: %+v", cache) |
| 492 | } |
| 493 | } |
| 494 | |
| 495 | // Remove the old caches which are too old. |