Conversation
📝 WalkthroughWalkthroughAdds a TaskScheduler service and CLI entry that run four maintenance tasks (session cleanup, search index optimization, statistics aggregation, backup creation); normalizes search DB driver naming; registers the scheduler service; and adds PHPUnit tests for success and failure scenarios. Changes
Sequence DiagramsequenceDiagram
participant CLI as "bin/scheduler.php"
participant DI as "DI Container"
participant TS as "TaskScheduler"
participant AS as "AdminSession"
participant ES as "Elasticsearch/OpenSearch"
participant Stats as "Statistics"
participant Backup as "Backup"
CLI->>DI: bootstrap & compile container
CLI->>DI: get(service: phpmyfaq.scheduler.task-scheduler)
DI-->>CLI: TaskScheduler instance
CLI->>TS: run()
TS->>AS: cleanupSessions() -> deleteSessions(0, cutoff)
AS-->>TS: deletion result
TS->>ES: optimizeSearchIndex() -> forcemerge (if enabled)
ES-->>TS: merge result / error
TS->>Stats: aggregateStatistics() -> query totals
Stats-->>TS: totals
TS->>Backup: createBackup() -> export(BACKUP_TYPE_DATA)
Backup-->>TS: fileName / error
TS-->>CLI: aggregated results array
CLI->>CLI: output pretty JSON
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
🚥 Pre-merge checks | ✅ 3 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
No actionable comments were generated in the recent review. 🎉 🧹 Recent nitpick comments
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Fix all issues with AI agents
In `@phpmyfaq/src/phpMyFAQ/Scheduler/TaskScheduler.php`:
- Around line 59-78: The cleanupSessions() method calls
$this->adminSession->deleteSessions(...) without catching exceptions; wrap that
call in a try/catch so any thrown exception is caught, logged via
$this->configuration->getLogger()->error() (include the exception message/trace
and the cutoffTimestamp/retentionSeconds context), and ensure $success is set to
false on exception before returning the same result array; this mirrors the
exception-handling pattern used in other task methods and prevents uncaught
exceptions from propagating out of cleanupSessions().
- Around line 140-148: aggregateStatistics() currently lets exceptions from
$this->statistics->totalFaqs() or $this->adminSession->getNumberOfSessions()
bubble up; wrap the calls in a try/catch (mirroring optimizeSearchIndex() and
createBackup()) so any Exception is caught and the method returns a failure
payload (e.g. 'success' => false, include 'error' => $e->getMessage(), and still
set 'generatedAt'), using aggregateStatistics(), totalFaqs(),
getNumberOfSessions(), $this->statistics and $this->adminSession to locate the
code to modify.
- Around line 46-54: run() currently evaluates cleanupSessions(),
optimizeSearchIndex(), aggregateStatistics(), and createBackup() eagerly so an
exception in any (notably cleanupSessions() or aggregateStatistics()) aborts the
whole scheduler; update run() in TaskScheduler to invoke each task inside its
own try/catch (catch \Throwable), call cleanupSessions(), optimizeSearchIndex(),
aggregateStatistics(), and createBackup() separately, log the caught exception
(use the class logger or error mechanism already used elsewhere), and populate
the returned array with either the task result or a failure marker/null so a
single task failure doesn’t prevent the others from running.
In `@phpmyfaq/src/phpMyFAQ/Search.php`:
- Around line 204-222: The getDatabaseDriverClassName() function contains an
unreachable fallback 'sqlite3' in "return end($classNameParts) ?: 'sqlite3'";
remove the dead fallback and return the last element directly (ensuring the
return is a string) so the function simply returns the class basename. Update
getDatabaseDriverClassName(DatabaseDriver $databaseDriver) to return the last
part of explode('\\', $databaseDriver::class) (e.g., cast the end() result to
string) and leave resolveSearchDatabaseType() unchanged.
🧹 Nitpick comments (4)
phpmyfaq/src/phpMyFAQ/Scheduler/TaskScheduler.php (1)
88-96:forcemergewithmax_num_segments => 1is resource-intensive.Force-merging to a single segment is an expensive operation that can starve search performance on large indices while running. Consider using a higher segment count (e.g., 5) or making it configurable, and ensure this task runs during low-traffic windows.
bin/scheduler.php (2)
42-43: Mixing plain text and JSON output complicates machine parsing.The "Task scheduler finished." message before the JSON payload means the output is not valid JSON. If this is intended for cron/automation, consider writing the status message to STDERR or including it inside the JSON payload.
♻️ Proposed fix
-echo "Task scheduler finished.\n"; -echo json_encode($results, JSON_PRETTY_PRINT) . PHP_EOL; +fwrite(STDERR, "Task scheduler finished.\n"); +echo json_encode($results, JSON_PRETTY_PRINT) . PHP_EOL;
34-40: No error handling around container build or task execution.If
$container->compile()or$scheduler->run()throws, the script exits with an unhandled exception and exit code 255. Consider wrapping in a try/catch to log a clear error message and return a meaningful exit code.tests/phpMyFAQ/Scheduler/TaskSchedulerTest.php (1)
21-49: Good coverage of the happy path; consider adding a test forcleanupSessionsfailure.The
run()test verifies the happy path well. However, there's no test for thecleanupSessionsfailure branch (whendeleteSessionsreturns false), which would verify the warning log is triggered. Similarly,aggregateStatisticsisn't tested in isolation.
ffdea8a to
672f210
Compare
Summary by CodeRabbit
New Features
Tests