From 26d2a46c08c73492e39fb5130122d0fae65ce331 Mon Sep 17 00:00:00 2001 From: HB9HIL Date: Mon, 2 Feb 2026 22:07:00 +0100 Subject: [PATCH] first fixes of dxclustercache since new cache driver handling --- application/controllers/Dxcluster.php | 27 +++-- application/libraries/DxclusterCache.php | 120 ++--------------------- application/models/Dxcluster_model.php | 7 -- 3 files changed, 28 insertions(+), 126 deletions(-) diff --git a/application/controllers/Dxcluster.php b/application/controllers/Dxcluster.php index 928d3a8d9..40f4ae9d2 100644 --- a/application/controllers/Dxcluster.php +++ b/application/controllers/Dxcluster.php @@ -9,9 +9,9 @@ class Dxcluster extends CI_Controller { function __construct() { parent::__construct(); - $this->load->model('user_model'); + $this->load->is_loaded('user_model') ?: $this->load->model('user_model'); if(!$this->user_model->authorize(2)) { $this->session->set_flashdata('error', __("You're not allowed to do that!")); redirect('dashboard'); } - $this->load->model('dxcluster_model'); + $this->load->is_loaded('dxcluster_model') ?: $this->load->model('dxcluster_model'); } @@ -35,19 +35,21 @@ class Dxcluster extends CI_Controller { header('Content-Type: application/json'); if ($calls_found && !empty($calls_found)) { - echo json_encode($calls_found); + http_response_code(200); + echo json_encode($calls_found, JSON_PRETTY_PRINT); } else { - echo json_encode(['error' => 'not found']); + $this->_return_not_found(); } } function qrg_lookup($qrg) { - $call_found=$this->dxcluster_model->dxc_qrg_lookup($this->security->xss_clean($qrg)); - header('Content-Type: application/json'); + $call_found = $this->dxcluster_model->dxc_qrg_lookup($this->security->xss_clean($qrg)); + header('Content-Type: application/json'); if ($call_found) { + http_response_code(200); echo json_encode($call_found, JSON_PRETTY_PRINT); } else { - echo '{ "error": "not found" }'; + $this->_return_not_found(); } } @@ -57,11 +59,18 @@ class Dxcluster extends CI_Controller { $dxcc = $dxccobj->dxcc_lookup($call, $date); + header('Content-Type: application/json'); if ($dxcc) { - header('Content-Type: application/json'); + http_response_code(200); echo json_encode($dxcc, JSON_PRETTY_PRINT); } else { - echo '{ "error": "not found" }'; + $this->_return_not_found(); } } + + private function _return_not_found() { + header('Content-Type: application/json'); + http_response_code(404); + echo json_encode(['error' => 'not found'], JSON_PRETTY_PRINT); + } } diff --git a/application/libraries/DxclusterCache.php b/application/libraries/DxclusterCache.php index b8d2b6a08..013a9874b 100644 --- a/application/libraries/DxclusterCache.php +++ b/application/libraries/DxclusterCache.php @@ -77,35 +77,20 @@ class DxclusterCache { if (empty($logbook_key)) return; // Delete callsign cache - $this->deleteFile($this->getWorkedCallKey($logbook_key, $callsign)); + $this->_delete_from_cache($this->getWorkedCallKey($logbook_key, $callsign)); // Look up DXCC and continent from callsign $dxccobj = new Dxcc(null); $dxcc_info = $dxccobj->dxcc_lookup($callsign, date('Y-m-d')); if (!empty($dxcc_info['adif'])) { - $this->deleteFile($this->getWorkedDxccKey($logbook_key, $dxcc_info['adif'])); + $this->_delete_from_cache($this->getWorkedDxccKey($logbook_key, $dxcc_info['adif'])); } if (!empty($dxcc_info['cont'])) { - $this->deleteFile($this->getWorkedContKey($logbook_key, $dxcc_info['cont'])); + $this->_delete_from_cache($this->getWorkedContKey($logbook_key, $dxcc_info['cont'])); } } - /** - * Invalidate all worked cache for current user (bulk operations) - */ - public function invalidateAllWorkedForCurrentUser() { - // Skip if worked cache is disabled - if ($this->CI->config->item('enable_dxcluster_file_cache_worked') !== true) return; - - $logbook_key = $this->getCurrentUserLogbookKey(); - if (empty($logbook_key)) return; - - $this->invalidateByPrefix("dxcluster_worked_call_{$logbook_key}_"); - $this->invalidateByPrefix("dxcluster_worked_dxcc_{$logbook_key}_"); - $this->invalidateByPrefix("dxcluster_worked_cont_{$logbook_key}_"); - } - /** * Get current user's logbook key from session */ @@ -129,97 +114,12 @@ class DxclusterCache { // INTERNAL HELPERS // ========================================================================= - protected function deleteFile($cache_key) { - $cache_path = $this->getCachePath(); - if (!$cache_path) return; - @unlink($cache_path . $cache_key); - } - - protected function invalidateByPrefix($prefix) { - $cache_path = $this->getCachePath(); - if (!$cache_path) return; - - $handle = @opendir($cache_path); - if (!$handle) return; - - while (($filename = readdir($handle)) !== false) { - if (strpos($filename, $prefix) === 0) { - @unlink($cache_path . $filename); - } - } - closedir($handle); - } - - protected function getCachePath() { - $cache_path = $this->CI->config->item('cache_path'); - $cache_path = ($cache_path === '' || $cache_path === false) ? APPPATH . 'cache/' : $cache_path; - $cache_path = rtrim($cache_path, '/\\') . DIRECTORY_SEPARATOR; - return (is_dir($cache_path) && is_writable($cache_path)) ? $cache_path : false; - } - - // ========================================================================= - // GARBAGE COLLECTION - // ========================================================================= - - /** - * Run garbage collection with probability check (1% chance) - * Call this on each request when worked cache is enabled - */ - public function maybeRunGc() { - if (mt_rand(1, 100) === 1) { - $this->cleanExpiredCache(); - } - } - - /** - * Clean expired dxcluster cache files - * Uses file mtime for fast pre-filtering before reading file contents - */ - public function cleanExpiredCache() { - $cache_path = $this->getCachePath(); - if (!$cache_path || !is_readable($cache_path)) return; - - $handle = @opendir($cache_path); - if (!$handle) return; - - $now = time(); - $deleted = 0; - - // Max TTL for dxcluster files: raw=59s, worked=900s - use 900s + buffer - $max_ttl = 1000; - - while (($filename = readdir($handle)) !== false) { - // Only process dxcluster cache files - if (strpos($filename, 'dxcluster_') !== 0) continue; - - $file = $cache_path . $filename; - if (!is_file($file)) continue; - - // Fast pre-filter: skip files modified recently (can't be expired yet) - $mtime = @filemtime($file); - if ($mtime !== false && ($now - $mtime) < $max_ttl) { - continue; - } - - // File is old enough to potentially be expired - read and verify - $data = @unserialize(@file_get_contents($file)); - if (!is_array($data) || !isset($data['time'], $data['ttl'])) { - @unlink($file); - $deleted++; - continue; - } - - // Check if expired - if ($data['ttl'] > 0 && $now > $data['time'] + $data['ttl']) { - @unlink($file); - $deleted++; - } - } - - closedir($handle); - - if ($deleted > 0) { - log_message('debug', "DXCluster cache GC: deleted {$deleted} expired files"); - } + protected function _delete_from_cache($cache_key) { + $this->CI->load->driver('cache', [ + 'adapter' => $this->CI->config->item('cache_adapter') ?? 'file', + 'backup' => $this->CI->config->item('cache_backup') ?? 'file', + 'key_prefix' => $this->CI->config->item('cache_key_prefix') ?? '' + ]); + $this->CI->cache->delete($cache_key); } } diff --git a/application/models/Dxcluster_model.php b/application/models/Dxcluster_model.php index 70e6c8d63..24f4f38d1 100644 --- a/application/models/Dxcluster_model.php +++ b/application/models/Dxcluster_model.php @@ -58,13 +58,6 @@ class Dxcluster_model extends CI_Model { 'backup' => $this->config->item('cache_backup') ?? 'file', 'key_prefix' => $this->config->item('cache_key_prefix') ?? '' ]); - - // Garbage collection: 1% chance to clean expired cache files - // Only needed when worked cache is enabled (creates many per-callsign files) - if ($cache_worked_enabled) { - $this->load->library('DxclusterCache'); - $this->dxclustercache->maybeRunGc(); - } } if($this->session->userdata('user_date_format')) {