Skip to main content

NIIA Watcher Daemon

The NIIA Watcher daemon monitors file system changes with intelligent filtering and event batching, providing real-time updates to the Monolex application.

Overview

┌─────────────────────────────────────────────────────────────────────┐
│               NIIA WATCHER ARCHITECTURE                             │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│   File System                                                       │
│       │                                                             │
│       │ inotify (Linux) / FSEvents (macOS) / ReadDirectoryChanges   │
│       ▼                                                             │
│   ┌─────────────────────────────────────────────────────────────┐   │
│   │  niia-watcher-daemon (2.75MB)                               │   │
│   │                                                             │   │
│   │  ┌──────────────┐    ┌──────────────┐    ┌──────────────┐   │   │
│   │  │ Event        │───→│ Filter       │───→│ Batcher      │   │   │
│   │  │ Collector    │    │ Engine       │    │ (debounce)   │   │   │
│   │  └──────────────┘    └──────────────┘    └──────────────┘   │   │
│   │                                                 │           │   │
│   └─────────────────────────────────────────────────│───────────┘   │
│                                                     ▼               │
│   Unix Socket ───────────────────────────────────────────────────── │
│                                                     │               │
│   Tauri App                                         │               │
│   ┌─────────────────────────────────────────────────│───────────┐   │
│   │  WatcherClient                                  ▼           │   │
│   │  ├── on_create(path)                                        │   │
│   │  ├── on_modify(path)                                        │   │
│   │  ├── on_delete(path)                                        │   │
│   │  └── on_rename(old_path, new_path)                          │   │
│   └─────────────────────────────────────────────────────────────┘   │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

Features

Intelligent Filtering

Pre-configured ignore patterns:
  • .git/ directories
  • node_modules/
  • Build artifacts (target/, dist/, build/)
  • Temporary files (*.tmp, *.swp)
  • OS files (.DS_Store, Thumbs.db)

Event Batching

Debounces rapid file changes:
File saved 5 times in 100ms:
├── Modify event 1 (t=0ms)
├── Modify event 2 (t=20ms)
├── Modify event 3 (t=40ms)
├── Modify event 4 (t=60ms)
└── Modify event 5 (t=80ms)

With batching (50ms debounce):
└── Single batched event (t=130ms)

Cross-Platform Support

PlatformBackend
macOSFSEvents
Linuxinotify
WindowsReadDirectoryChangesW

Events

Event Types

pub enum WatcherEvent {
    Create { path: PathBuf },
    Modify { path: PathBuf },
    Delete { path: PathBuf },
    Rename { old_path: PathBuf, new_path: PathBuf },
}

Event Format

JSON over Unix socket:
{
  "type": "modify",
  "path": "/Users/user/project/src/main.rs",
  "timestamp": 1705312345678
}

Configuration

Watch Paths

// Add watch path
watcher.watch("/Users/user/project", RecursiveMode::Recursive)?;

// Remove watch path
watcher.unwatch("/Users/user/project")?;

Ignore Patterns

Default patterns:
.git/**
node_modules/**
target/**
dist/**
build/**
*.tmp
*.swp
.DS_Store
Thumbs.db
Custom patterns can be added via configuration.

Usage

Starting the Watcher

// From Tauri backend
await invoke("start_watcher");

// Add watch path
await invoke("watcher_add_path", { path: "/Users/user/project" });

Listening to Events

import { listen } from "@tauri-apps/api/event";

// Listen for file changes
await listen("watcher-event", (event) => {
    const { type, path } = event.payload;

    switch (type) {
        case "create":
            console.log(`Created: ${path}`);
            break;
        case "modify":
            console.log(`Modified: ${path}`);
            break;
        case "delete":
            console.log(`Deleted: ${path}`);
            break;
        case "rename":
            console.log(`Renamed: ${event.payload.old_path}${path}`);
            break;
    }
});

Database Integration

Watcher events are persisted to SQLite:
CREATE TABLE watcher_events (
    id INTEGER PRIMARY KEY,
    event_type TEXT NOT NULL,
    path TEXT NOT NULL,
    old_path TEXT,
    timestamp INTEGER NOT NULL,
    processed INTEGER DEFAULT 0
);

CREATE INDEX idx_watcher_path ON watcher_events(path);
CREATE INDEX idx_watcher_timestamp ON watcher_events(timestamp);
Database location: ~/Library/Application Support/Monolex/protocols/niia/database/niia-watcher.db

Characteristics

MetricValue
Binary size2.75MB
Memory usageLow
Event latencyFast
Watched pathsScalable
ThroughputHigh

Logging

# View watcher logs
tail -f /tmp/niia-watcher.log

# Example output
[2024-01-15T10:30:00Z] INFO  Starting NIIA Watcher
[2024-01-15T10:30:00Z] INFO  Watching: /Users/user/project
[2024-01-15T10:30:01Z] DEBUG File modified: src/main.rs
[2024-01-15T10:30:01Z] DEBUG Event batched, waiting 50ms
[2024-01-15T10:30:01Z] INFO  Emitting batched event for src/main.rs

Troubleshooting

Watcher Not Starting

# Check if already running
ps aux | grep niia-watcher

# Check logs
cat /tmp/niia-watcher.log

# Verify binary exists
ls -la src-tauri/binaries/niia-watcher-daemon-*

Events Not Firing

  1. Check if path is being watched
  2. Verify path isn’t ignored by filters
  3. Check event batching delay
  4. Review watcher logs

High CPU Usage

Usually caused by:
  • Watching too many files
  • Rapid file changes (reduce debounce time)
  • Recursive watch on large directories
Solution: Add ignore patterns for noisy directories.

SMPC/OFAC Applied

PrincipleApplication
SMPCSingle purpose: file watching only
Simple event types: create/modify/delete/rename
Clear ignore patterns
OFACBatching emerged from event storm handling
Filtering emerged from noise reduction need
Database storage emerged from persistence need