diff --git a/config/services.yaml b/config/services.yaml
index beaba80..d577bb1 100644
--- a/config/services.yaml
+++ b/config/services.yaml
@@ -190,6 +190,12 @@ services:
App\Tag\TagRoutingService: ~
+ App\Tag\TagVectorIndexHealthService:
+ arguments:
+ $tagsNdjsonPath: '%mto.knowledge.tags_ndjson%'
+ $vectorTagsIndexPath: '%mto.knowledge.vector_tags_index%'
+ $vectorTagsMetaPath: '%mto.knowledge.vector_tags_index_meta%'
+
# ------------------------------------------------------------
# Tag Rebuild Jobs
# ------------------------------------------------------------
diff --git a/src/Controller/Admin/DashboardController.php b/src/Controller/Admin/DashboardController.php
index e925f54..bd11017 100644
--- a/src/Controller/Admin/DashboardController.php
+++ b/src/Controller/Admin/DashboardController.php
@@ -5,6 +5,7 @@ namespace App\Controller\Admin;
use App\Index\IndexMetaManager;
use App\Ingest\IngestFlow;
+use App\Tag\TagVectorIndexHealthService;
use App\Vector\VectorIndexHealthService;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\RedirectResponse;
@@ -23,7 +24,7 @@ final class DashboardController extends AbstractController
#[Route('/admin/dashboard', name: 'admin_dashboard')]
- public function dashboard(IndexMetaManager $metaManager,VectorIndexHealthService $health): Response
+ public function dashboard(IndexMetaManager $metaManager,VectorIndexHealthService $health,TagVectorIndexHealthService $tagHealth): Response
{
$chunkCount = $metaManager->getRuntimeChunkCount();
$limit = IngestFlow::CHUNK_LIMIT_HARD;
@@ -32,6 +33,9 @@ final class DashboardController extends AbstractController
'chunkCount' => $chunkCount,
'chunkLimit' => $limit,
'vectorHealth' => $health->check(),
+ 'tagVectorHealth' => $tagHealth->check(),
]);
}
+
+
}
diff --git a/src/Tag/TagVectorIndexHealthService.php b/src/Tag/TagVectorIndexHealthService.php
new file mode 100644
index 0000000..79977dc
--- /dev/null
+++ b/src/Tag/TagVectorIndexHealthService.php
@@ -0,0 +1,68 @@
+tagsNdjsonPath);
+ $vectorExists = is_file($this->vectorTagsIndexPath);
+ $metaExists = is_file($this->vectorTagsMetaPath);
+
+ $ndjsonTagCount = 0;
+
+ if ($ndjsonExists) {
+ $h = @fopen($this->tagsNdjsonPath, 'r');
+ if ($h !== false) {
+ while (($line = fgets($h)) !== false) {
+ $line = trim($line);
+ if ($line === '') continue;
+
+ $data = json_decode($line, true);
+ if (is_array($data) && !empty($data['tag_id']) && !empty($data['text'])) {
+ $ndjsonTagCount++;
+ }
+ }
+ fclose($h);
+ }
+ }
+
+ $vectorTagCount = 0;
+ if ($metaExists) {
+ $meta = json_decode((string) file_get_contents($this->vectorTagsMetaPath), true);
+ if (is_array($meta)) {
+ $vectorTagCount = count($meta);
+ }
+ }
+
+ $status = $this->determineStatus($ndjsonTagCount, $vectorExists, $metaExists, $vectorTagCount);
+
+ return [
+ 'tags_ndjson_exists' => $ndjsonExists,
+ 'tags_ndjson_count' => $ndjsonTagCount,
+ 'vector_exists' => $vectorExists,
+ 'meta_exists' => $metaExists,
+ 'vector_tag_count' => $vectorTagCount,
+ 'status' => $status,
+ ];
+ }
+
+ private function determineStatus(int $ndjsonTagCount, bool $vectorExists, bool $metaExists, int $vectorTagCount): string
+ {
+ if ($ndjsonTagCount === 0 && !$vectorExists && !$metaExists) return 'OK_EMPTY';
+ if ($ndjsonTagCount > 0 && $vectorExists && $metaExists && $vectorTagCount === $ndjsonTagCount) return 'OK';
+ if ($ndjsonTagCount === 0 && ($vectorExists || $metaExists)) return 'INCONSISTENT_STALE_VECTOR';
+ if ($ndjsonTagCount > 0 && (!$vectorExists || !$metaExists)) return 'INCONSISTENT_MISSING_VECTOR';
+ if ($ndjsonTagCount !== $vectorTagCount) return 'INCONSISTENT_COUNT_MISMATCH';
+ return 'UNKNOWN';
+ }
+}
\ No newline at end of file
diff --git a/src/Vector/VectorIndexHealthService.php b/src/Vector/VectorIndexHealthService.php
index b4b23f5..4bd4b97 100644
--- a/src/Vector/VectorIndexHealthService.php
+++ b/src/Vector/VectorIndexHealthService.php
@@ -4,7 +4,7 @@ declare(strict_types=1);
namespace App\Vector;
-final class VectorIndexHealthService
+final readonly class VectorIndexHealthService
{
public function __construct(
private string $indexNdjsonPath,
diff --git a/templates/admin/base.html.twig b/templates/admin/base.html.twig
index c32c2dc..2510259 100644
--- a/templates/admin/base.html.twig
+++ b/templates/admin/base.html.twig
@@ -6,7 +6,9 @@
{% block title %}Admin{% endblock %}
{% block stylesheets %}
+
+
{% endblock %}
@@ -51,11 +53,11 @@
{% set route = app.request.attributes.get('_route') %}
-