Merge pull request #2896 from HB9HIL/dxclustercache_fix

Dxclustercache fix since we made various caching drivers available
This commit is contained in:
Fabian Berg
2026-02-03 17:17:56 +00:00
committed by GitHub
5 changed files with 105 additions and 307 deletions

View File

@@ -9,17 +9,27 @@ 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');
}
function spots($band, $age = '', $de = '', $mode = 'All') {
public function spots($band, $age = '', $de = '', $mode = 'All') {
// Sanitize inputs
$band = $this->security->xss_clean($band);
$mode = $this->security->xss_clean($mode);
// Only load cache driver if caching is enabled
if (($this->config->item('enable_dxcluster_file_cache_band') ?? false) || ($this->config->item('enable_dxcluster_file_cache_worked') ?? false)) {
$this->load->driver('cache', [
'adapter' => $this->config->item('cache_adapter') ?? 'file',
'backup' => $this->config->item('cache_backup') ?? 'file',
'key_prefix' => $this->config->item('cache_key_prefix') ?? ''
]);
}
if ($age == '') {
$age = $this->optionslib->get_option('dxcluster_maxage') ?? 60;
} else {
@@ -35,33 +45,42 @@ 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');
public function qrg_lookup($qrg) {
$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();
}
}
function call($call) {
public function call($call) {
$date = date('Y-m-d', time());
$dxccobj = new Dxcc($date);
$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);
}
}

View File

@@ -24,14 +24,14 @@ class DxclusterCache {
/**
* Generate RAW spot cache key (instance-wide, shared by all users)
*/
public function getRawCacheKey($maxage, $band) {
public function get_raw_cache_key($maxage, $band) {
return "dxcluster_raw_{$maxage}_{$band}_Any_All";
}
/**
* Generate logbook IDs key component (user-specific)
*/
public function getLogbookKey($user_id, $logbook_ids, $confirmation_prefs) {
public function get_logbook_key($user_id, $logbook_ids, $confirmation_prefs) {
$logbook_ids_str = implode('_', $logbook_ids);
$confirmation_hash = md5($confirmation_prefs);
return "{$user_id}_{$logbook_ids_str}_{$confirmation_hash}";
@@ -40,21 +40,21 @@ class DxclusterCache {
/**
* Generate WORKED callsign cache key
*/
public function getWorkedCallKey($logbook_key, $callsign) {
public function get_worked_call_key($logbook_key, $callsign) {
return "dxcluster_worked_call_{$logbook_key}_{$callsign}";
}
/**
* Generate WORKED DXCC cache key
*/
public function getWorkedDxccKey($logbook_key, $dxcc) {
public function get_worked_dxcc_key($logbook_key, $dxcc) {
return "dxcluster_worked_dxcc_{$logbook_key}_{$dxcc}";
}
/**
* Generate WORKED continent cache key
*/
public function getWorkedContKey($logbook_key, $cont) {
public function get_worked_cont_key($logbook_key, $cont) {
return "dxcluster_worked_cont_{$logbook_key}_{$cont}";
}
@@ -66,50 +66,35 @@ class DxclusterCache {
* Invalidate cache after QSO add/edit/delete for current user
* @param string $callsign - The worked callsign
*/
public function invalidateForCallsign($callsign) {
public function invalidate_for_callsign($callsign) {
// Skip if worked cache is disabled
if ($this->CI->config->item('enable_dxcluster_file_cache_worked') !== true) return;
if (empty($callsign)) return;
// Get current user's logbook key
$logbook_key = $this->getCurrentUserLogbookKey();
$logbook_key = $this->_get_current_user_logbook_key();
if (empty($logbook_key)) return;
// Delete callsign cache
$this->deleteFile($this->getWorkedCallKey($logbook_key, $callsign));
$this->_delete_from_cache($this->get_worked_call_key($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->get_worked_dxcc_key($logbook_key, $dxcc_info['adif']));
}
if (!empty($dxcc_info['cont'])) {
$this->deleteFile($this->getWorkedContKey($logbook_key, $dxcc_info['cont']));
$this->_delete_from_cache($this->get_worked_cont_key($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
*/
protected function getCurrentUserLogbookKey() {
private function _get_current_user_logbook_key() {
$user_id = $this->CI->session->userdata('user_id');
$active_logbook = $this->CI->session->userdata('active_station_logbook');
@@ -122,104 +107,19 @@ class DxclusterCache {
if (empty($logbook_ids)) return null;
return $this->getLogbookKey($user_id, $logbook_ids, $confirmation_prefs);
return $this->get_logbook_key($user_id, $logbook_ids, $confirmation_prefs);
}
// =========================================================================
// 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");
}
private 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);
}
}

View File

@@ -27,8 +27,11 @@ class Dxcluster_model extends CI_Model {
'ISCAT', 'JT6M', 'FST4', 'FST4W', 'FREEDV', 'VARA'
];
protected $cache_band_enabled;
public function __construct() {
$this->load->Model('Modes');
$this->load->is_loaded('Modes') ?: $this->load->model('Modes');
$this->db->where('bandedges.userid', $this->session->userdata('user_id'));
$query = $this->db->get('bandedges');
$result = $query->result_array();
@@ -41,31 +44,12 @@ class Dxcluster_model extends CI_Model {
$query = $this->db->get('bandedges');
$this->bandedges = $query->result_array();
}
$this->cache_band_enabled = ($this->config->item('enable_dxcluster_file_cache_band') ?? false);
}
// Main function to get spot list from DXCache and process it
public function dxc_spotlist($band = '20m', $maxage = 60, $de = '', $mode = 'All') {
$this->load->helper(array('psr4_autoloader'));
// Check if file caching is enabled in config
$cache_band_enabled = $this->config->item('enable_dxcluster_file_cache_band') === true;
$cache_worked_enabled = $this->config->item('enable_dxcluster_file_cache_worked') === true;
// Only load cache driver if caching is enabled
if ($cache_band_enabled || $cache_worked_enabled) {
$this->load->driver('cache', [
'adapter' => $this->config->item('cache_adapter') ?? 'file',
'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')) {
$custom_date_format = $this->session->userdata('user_date_format');
@@ -81,17 +65,17 @@ class Dxcluster_model extends CI_Model {
$dxcache_url = $dxcache_url . '/spots/'.$band;
}
$this->load->model('logbook_model');
$this->load->is_loaded('logbook_model') ?: $this->load->model('logbook_model');
$logbooks_locations_array = $this->logbooks_model->list_logbook_relationships($this->session->userdata('active_station_logbook'));
// Cache key for RAW cluster response (instance-wide, no worked status)
// Use DxclusterCache library for centralized key generation
$this->load->library('DxclusterCache');
$raw_cache_key = $this->dxclustercache->getRawCacheKey($maxage, $band);
$raw_cache_key = $this->dxclustercache->get_raw_cache_key($maxage, $band);
// Check cache for raw processed spots (without worked status)
$spotsout = null;
if ($cache_band_enabled) {
if ($this->cache_band_enabled) {
$spotsout = $this->cache->get($raw_cache_key);
}
@@ -149,7 +133,7 @@ class Dxcluster_model extends CI_Model {
log_message('debug', 'DXCluster: Empty array received from ' . $dxcache_url . ' (no spots available)');
return [];
}
$date = date('Ymd', time());
$date = date('Y-m-d', time());
$dxccObj = new DXCC($date);
@@ -171,7 +155,7 @@ class Dxcluster_model extends CI_Model {
$singlespot->frequency = floatval($singlespot->frequency);
// Validate against amateur band allocations (skip non-amateur frequencies)
if (!$this->isFrequencyInAmateurBand($singlespot->frequency)) {
if (!$this->_is_frequency_in_amateurband($singlespot->frequency)) {
continue;
}
@@ -184,7 +168,7 @@ class Dxcluster_model extends CI_Model {
// Only determine mode if not provided by cluster
if (!isset($singlespot->mode) || empty($singlespot->mode)) {
$singlespot->mode = $this->get_mode($singlespot);
$singlespot->mode = $this->_get_mode($singlespot);
} else {
// Normalize cluster-provided mode to lowercase
$singlespot->mode = strtolower($singlespot->mode);
@@ -192,7 +176,7 @@ class Dxcluster_model extends CI_Model {
// Only determine submode if not provided by cluster
if (!isset($singlespot->submode) || empty($singlespot->submode)) {
$singlespot->submode = $this->get_submode($singlespot);
$singlespot->submode = $this->_get_submode($singlespot);
} else {
// Normalize cluster-provided submode to uppercase
$singlespot->submode = strtoupper($singlespot->submode);
@@ -248,14 +232,14 @@ class Dxcluster_model extends CI_Model {
}
// Extract park references from message
$singlespot = $this->enrich_spot_metadata($singlespot);
$singlespot = $this->_enrich_spot_metadata($singlespot);
// Collect spots for batch processing
$spotsout[] = $singlespot;
}
// Cache the RAW processed spots (WITHOUT worked status) - instance-wide
if ($cache_band_enabled && !empty($spotsout)) {
if ($this->cache_band_enabled && !empty($spotsout)) {
$this->cache->save($raw_cache_key, $spotsout, 59);
}
}
@@ -265,7 +249,7 @@ class Dxcluster_model extends CI_Model {
$de_lower = strtolower($de);
$filter_continent = ($de != '' && $de != 'Any');
$spotsout = array_filter($spotsout, function($spot) use ($mode, $de_lower, $filter_continent) {
if ($mode != 'All' && !$this->modefilter($spot, $mode)) return false;
if ($mode != 'All' && !$this->_modefilter($spot, $mode)) return false;
if ($filter_continent && ($de_lower != strtolower($spot->dxcc_spotter->cont ?? ''))) return false;
return true;
});
@@ -357,13 +341,14 @@ class Dxcluster_model extends CI_Model {
return $spotsout;
} // Determine mode with priority: POTA/SOTA mode > message keywords > frequency-based
function get_mode($spot) {
private function _get_mode($spot) {
// Priority 0: If spot already has a valid mode from cluster, use it
if (isset($spot->mode) && !empty($spot->mode)) {
$existingMode = strtolower($spot->mode);
// Validate it's a known mode category
if (in_array($existingMode, ['cw', 'phone', 'digi', 'ssb'])) {
return $this->mapToModeCategory($existingMode);
return $this->_map_to_mode_category($existingMode);
}
}
@@ -372,10 +357,10 @@ class Dxcluster_model extends CI_Model {
$sotaMode = $spot->sota_mode ?? $spot->dxcc_spotted->sota_mode ?? null;
if (!empty($potaMode)) {
return $this->mapToModeCategory($potaMode);
return $this->_map_to_mode_category($potaMode);
}
if (!empty($sotaMode)) {
return $this->mapToModeCategory($sotaMode);
return $this->_map_to_mode_category($sotaMode);
}
// Priority 2: Message keywords (explicit mode in message text)
@@ -397,7 +382,7 @@ class Dxcluster_model extends CI_Model {
// Priority 3: Frequency-based mode (from bandedges table)
// If frequency falls within a defined band edge, use that mode
$frequencyMode = $this->Frequency2Mode($spot->frequency);
$frequencyMode = $this->_frequency_to_mode($spot->frequency);
if ($frequencyMode != '') {
return $frequencyMode;
}
@@ -407,7 +392,7 @@ class Dxcluster_model extends CI_Model {
}
// Map specific mode names to mode categories (phone/cw/digi)
function mapToModeCategory($mode) {
private function _map_to_mode_category($mode) {
$modeUpper = strtoupper($mode);
// CW modes
@@ -432,7 +417,7 @@ class Dxcluster_model extends CI_Model {
}
// Determine submode for more specific mode classification
function get_submode($spot) {
private function _get_submode($spot) {
// Priority 0: If spot already has a valid submode from cluster, use it
if (isset($spot->submode) && !empty($spot->submode)) {
return strtoupper($spot->submode);
@@ -482,16 +467,16 @@ class Dxcluster_model extends CI_Model {
return strtoupper($mode);
}
function modefilter($spot, $mode) {
private function _modefilter($spot, $mode) {
$mode = strtolower($mode); // Normalize case
$spotMode = strtolower($spot->mode ?? ''); // Get already-determined mode
// Since get_mode() already determined the mode using priority logic
// Since _get_mode() already determined the mode using priority logic
// (frequency > POTA/SOTA > message), we can directly compare
return $spotMode === $mode;
}
public function Frequency2Mode($frequency) {
private function _frequency_to_mode($frequency) {
// Ensure frequency is in Hz if input is in kHz
if ($frequency < 1_000_000) {
$frequency *= 1000;
@@ -505,29 +490,12 @@ class Dxcluster_model extends CI_Model {
return '';
}
public function isFrequencyInMode($frequency, $mode) {
// Ensure frequency is in Hz if input is in kHz
if ($frequency < 1_000_000) {
$frequency *= 1000;
}
foreach ($this->bandedges as $band) {
if (strtolower($band['mode']) === strtolower($mode)) {
if ($frequency >= $band['frequencyfrom'] && $frequency < $band['frequencyto']) {
return true;
}
}
}
return false;
}
/**
* Check if frequency falls within amateur band allocations
* @param float $frequency Frequency in Hz
* @return bool True if frequency is in amateur band
*/
public function isFrequencyInAmateurBand($frequency) {
private function _is_frequency_in_amateurband($frequency) {
// Ensure frequency is in Hz if input is in kHz
if ($frequency < 1_000_000) {
$frequency *= 1000;
@@ -543,7 +511,7 @@ class Dxcluster_model extends CI_Model {
}
public function dxc_qrg_lookup($qrg, $maxage = 120) {
$this->load->helper(array('psr4_autoloader'));
if (is_numeric($qrg)) {
$dxcache_url = ($this->optionslib->get_option('dxcache_url') == '' ? 'https://dxc.wavelog.org/dxcache' : $this->optionslib->get_option('dxcache_url'));
@@ -585,98 +553,6 @@ class Dxcluster_model extends CI_Model {
}
}
function check_if_continent_worked_in_logbook($cont, $StationLocationsArray = null, $band = null, $mode = null) {
if ($StationLocationsArray == null) {
$this->load->model('logbooks_model');
$logbooks_locations_array = $this->logbooks_model->list_logbook_relationships($this->session->userdata('active_station_logbook'));
} else {
$logbooks_locations_array = $StationLocationsArray;
}
$this->db->select('COL_CONT');
$this->db->where_in('station_id', $logbooks_locations_array);
$this->db->where('COL_CONT', $cont);
if (isset($mode)) {
$this->db->where(" COL_MODE in ".$this->Modes->get_modes_from_qrgmode($mode,true));
}
$band = ($band == 'All') ? null : $band;
if ($band != null && $band != 'SAT') {
$this->db->where('COL_BAND', $band);
} else if ($band == 'SAT') {
// Where col_sat_name is not empty
$this->db->where('COL_SAT_NAME !=', '');
}
$this->db->limit('2');
$query = $this->db->get($this->config->item('table_name'));
return $query->num_rows();
}
function check_if_continent_cnfmd_in_logbook($cont, $StationLocationsArray = null, $band = null, $mode = null) {
if ($StationLocationsArray == null) {
$this->load->model('logbooks_model');
$logbooks_locations_array = $this->logbooks_model->list_logbook_relationships($this->session->userdata('active_station_logbook'));
} else {
$logbooks_locations_array = $StationLocationsArray;
}
$user_default_confirmation = $this->session->userdata('user_default_confirmation');
$extrawhere = '';
if (isset($user_default_confirmation) && strpos($user_default_confirmation, 'Q') !== false) {
$extrawhere = "COL_QSL_RCVD='Y'";
}
if (isset($user_default_confirmation) && strpos($user_default_confirmation, 'L') !== false) {
if ($extrawhere != '') {
$extrawhere .= " OR";
}
$extrawhere .= " COL_LOTW_QSL_RCVD='Y'";
}
if (isset($user_default_confirmation) && strpos($user_default_confirmation, 'E') !== false) {
if ($extrawhere != '') {
$extrawhere .= " OR";
}
$extrawhere .= " COL_EQSL_QSL_RCVD='Y'";
}
if (isset($user_default_confirmation) && strpos($user_default_confirmation, 'Z') !== false) {
if ($extrawhere != '') {
$extrawhere .= " OR";
}
$extrawhere .= " COL_QRZCOM_QSO_DOWNLOAD_STATUS='Y'";
}
$this->db->select('COL_CONT');
$this->db->where_in('station_id', $logbooks_locations_array);
$this->db->where('COL_CONT', $cont);
if (isset($mode)) {
$this->db->where(" COL_MODE in ".$this->Modes->get_modes_from_qrgmode($mode,true));
}
$band = ($band == 'All') ? null : $band;
if ($band != null && $band != 'SAT') {
$this->db->where('COL_BAND', $band);
} else if ($band == 'SAT') {
// Where col_sat_name is not empty
$this->db->where('COL_SAT_NAME !=', '');
}
if ($extrawhere != '') {
$this->db->where('(' . $extrawhere . ')');
} else {
$this->db->where("1=0");
}
$this->db->limit('2');
$query = $this->db->get($this->config->item('table_name'));
return $query->num_rows();
}
/**
* Enrich spot metadata with park references and contest detection
* Extracts SOTA/POTA/IOTA/WWFF references and detects contest spots
@@ -684,7 +560,7 @@ class Dxcluster_model extends CI_Model {
* @param object $spot - Spot object with message and dxcc_spotted properties
* @return object - Spot object with enriched dxcc_spotted containing references and isContest flag
*/
function enrich_spot_metadata($spot) {
private function _enrich_spot_metadata($spot) {
// Ensure dxcc_spotted object exists
if (!property_exists($spot, 'dxcc_spotted') || !is_object($spot->dxcc_spotted)) {
$spot->dxcc_spotted = (object)[];

View File

@@ -899,7 +899,7 @@ class Logbook_model extends CI_Model {
}
// Invalidate DXCluster cache for this callsign
$this->dxclustercache->invalidateForCallsign($data['COL_CALL']);
$this->dxclustercache->invalidate_for_callsign($data['COL_CALL']);
// Return QSO ID for ADIF generation
return $last_id;
@@ -1674,7 +1674,7 @@ class Logbook_model extends CI_Model {
$retvals['success']=true;
// Invalidate DXCluster cache for this callsign
$this->dxclustercache->invalidateForCallsign($data['COL_CALL']);
$this->dxclustercache->invalidate_for_callsign($data['COL_CALL']);
} catch (Exception $e) {
$retvals['success']=false;
$retvals['detail']=$e;
@@ -2715,13 +2715,16 @@ class Logbook_model extends CI_Model {
// Load cache driver for file caching
$cache_enabled = $this->config->item('enable_dxcluster_file_cache_worked') === true;
if ($cache_enabled && !isset($this->cache)) {
$this->load->driver('cache', [
'adapter' => $this->config->item('cache_adapter') ?? 'file',
'backup' => $this->config->item('cache_backup') ?? 'file',
'key_prefix' => $this->config->item('cache_key_prefix') ?? ''
]);
}
// Gets already loaded in dxcluster controller
//
// if ($cache_enabled && !isset($this->cache)) {
// $this->load->driver('cache', [
// 'adapter' => $this->config->item('cache_adapter') ?? 'file',
// 'backup' => $this->config->item('cache_backup') ?? 'file',
// 'key_prefix' => $this->config->item('cache_key_prefix') ?? ''
// ]);
// }
// Cache TTL in seconds (15 minutes = 900 seconds)
$cache_ttl = 900;
@@ -2743,7 +2746,7 @@ class Logbook_model extends CI_Model {
// Build cache key with user_id, logbook_ids, and confirmation preference
$user_id = $this->session->userdata('user_id');
$logbook_ids_key = $this->dxclustercache->getLogbookKey($user_id, $logbooks_locations_array, $user_default_confirmation);
$logbook_ids_key = $this->dxclustercache->get_logbook_key($user_id, $logbooks_locations_array, $user_default_confirmation);
$spots_by_callsign = []; // Group spots by callsign for processing
foreach ($spots as $spot) {
@@ -2781,7 +2784,7 @@ class Logbook_model extends CI_Model {
if (!isset($this->spot_status_cache[$cache_key])) {
// Check file cache
if ($cache_enabled) {
$file_cache_key = $this->dxclustercache->getWorkedCallKey($logbook_ids_key, $callsign);
$file_cache_key = $this->dxclustercache->get_worked_call_key($logbook_ids_key, $callsign);
$cached_data = $this->cache->get($file_cache_key);
if ($cached_data !== false) {
// Load from file cache into in-memory cache
@@ -2799,7 +2802,7 @@ class Logbook_model extends CI_Model {
if (!isset($this->spot_status_cache[$cache_key])) {
if ($cache_enabled) {
$file_cache_key = $this->dxclustercache->getWorkedDxccKey($logbook_ids_key, $dxcc);
$file_cache_key = $this->dxclustercache->get_worked_dxcc_key($logbook_ids_key, $dxcc);
$cached_data = $this->cache->get($file_cache_key);
if ($cached_data !== false) {
$this->spot_status_cache[$cache_key] = $cached_data;
@@ -2815,7 +2818,7 @@ class Logbook_model extends CI_Model {
if (!isset($this->spot_status_cache[$cache_key])) {
if ($cache_enabled) {
$file_cache_key = $this->dxclustercache->getWorkedContKey($logbook_ids_key, $cont);
$file_cache_key = $this->dxclustercache->get_worked_cont_key($logbook_ids_key, $cont);
$cached_data = $this->cache->get($file_cache_key);
if ($cached_data !== false) {
$this->spot_status_cache[$cache_key] = $cached_data;
@@ -3058,7 +3061,7 @@ class Logbook_model extends CI_Model {
// Save to file cache for 15 minutes
if ($cache_enabled) {
$file_cache_key = $this->dxclustercache->getWorkedCallKey($logbook_ids_key, $callsign);
$file_cache_key = $this->dxclustercache->get_worked_call_key($logbook_ids_key, $callsign);
$this->cache->save($file_cache_key, $data, $cache_ttl);
}
}
@@ -3067,7 +3070,7 @@ class Logbook_model extends CI_Model {
$this->spot_status_cache[$cache_key] = $data;
if ($cache_enabled) {
$file_cache_key = $this->dxclustercache->getWorkedDxccKey($logbook_ids_key, $dxcc);
$file_cache_key = $this->dxclustercache->get_worked_dxcc_key($logbook_ids_key, $dxcc);
$this->cache->save($file_cache_key, $data, $cache_ttl);
}
}
@@ -3076,7 +3079,7 @@ class Logbook_model extends CI_Model {
$this->spot_status_cache[$cache_key] = $data;
if ($cache_enabled) {
$file_cache_key = $this->dxclustercache->getWorkedContKey($logbook_ids_key, $cont);
$file_cache_key = $this->dxclustercache->get_worked_cont_key($logbook_ids_key, $cont);
$this->cache->save($file_cache_key, $data, $cache_ttl);
}
} // Cache NOT WORKED items (negative results) - store empty arrays
@@ -3087,7 +3090,7 @@ class Logbook_model extends CI_Model {
$this->spot_status_cache[$cache_key] = []; // Empty = not worked
if ($cache_enabled) {
$file_cache_key = $this->dxclustercache->getWorkedCallKey($logbook_ids_key, $callsign);
$file_cache_key = $this->dxclustercache->get_worked_call_key($logbook_ids_key, $callsign);
$this->cache->save($file_cache_key, [], $cache_ttl);
}
}
@@ -3098,7 +3101,7 @@ class Logbook_model extends CI_Model {
$this->spot_status_cache[$cache_key] = [];
if ($cache_enabled) {
$file_cache_key = $this->dxclustercache->getWorkedDxccKey($logbook_ids_key, $dxcc);
$file_cache_key = $this->dxclustercache->get_worked_dxcc_key($logbook_ids_key, $dxcc);
$this->cache->save($file_cache_key, [], $cache_ttl);
}
}
@@ -3109,7 +3112,7 @@ class Logbook_model extends CI_Model {
$this->spot_status_cache[$cache_key] = [];
if ($cache_enabled) {
$file_cache_key = $this->dxclustercache->getWorkedContKey($logbook_ids_key, $cont);
$file_cache_key = $this->dxclustercache->get_worked_cont_key($logbook_ids_key, $cont);
$this->cache->save($file_cache_key, [], $cache_ttl);
}
}
@@ -4351,7 +4354,7 @@ class Logbook_model extends CI_Model {
$this->db->delete("oqrs");
// Invalidate DXCluster cache for this callsign
$this->dxclustercache->invalidateForCallsign($callsign);
$this->dxclustercache->invalidate_for_callsign($callsign);
} else {
return;
}

View File

@@ -323,7 +323,7 @@ class Dxcc {
*/
function read_data($date = NULL) {
$CI = &get_instance();
$CI->load->driver('cache', [
$CI->load->is_loaded('cache') ?: $CI->load->driver('cache', [
'adapter' => $CI->config->item('cache_adapter') ?? 'file',
'backup' => $CI->config->item('cache_backup') ?? 'file',
'key_prefix' => $CI->config->item('cache_key_prefix') ?? ''