v2.5Erweitert
Plugin-Entwicklung
Die Plugin-Architektur erlaubt es, Velisch-Anwendungen zur Laufzeit zu erweitern, ohne den Kern neu zu kompilieren. Plugins sind kompilierte .vplugin-Dateien.
Architektur eines Plugins
Ein Plugin muss das Plugin-Trait implementieren:
// Datei: my_plugin.velin
struct MyPlugin {
config: Map<string, any>
}
impl Plugin for MyPlugin {
// Wird beim Laden aufgerufen
fn on_load(ctx: PluginContext) {
log.info("Plugin wird initialisiert...");
// Hooks registrieren
ctx.register_hook("on_request", |req| {
log.info("Request empfangen: " + req.path);
});
// Eigene Befehle hinzufügen
ctx.register_command("hello", || log.info("Hallo vom Plugin!"));
}
// Wird beim Entladen (oder Shutdown) aufgerufen
fn on_unload() {
log.info("Plugin wird gestoppt.");
}
}
// Export der Factory-Funktion
pub fn create(config: Map<string, any>): Plugin {
return MyPlugin { config: config };
}Lifecycle Hooks
Plugins können sich in verschiedene Phasen der Anwendung einklinken:
on_loadInitialisierung beim Laden
on_config_loadedNach dem Laden der Konfiguration
on_server_startBevor der HTTP-Server startet
on_requestMiddleware-ähnlicher Hook für jeden Request
on_errorGlobaler Error-Handler
on_unloadCleanup beim Entladen
Beispiel: Ein Metrik-Plugin
Ein praktisches Beispiel, das Request-Metriken sammelt und an Prometheus exportiert:
// metrics_plugin.velin
struct MetricsPlugin {
requestCount: number,
requestDurations: List<number>,
}
impl Plugin for MetricsPlugin {
fn on_load(ctx: PluginContext) {
self.requestCount = 0;
self.requestDurations = [];
// Request-Hook für Metriken
ctx.register_hook("on_request", |req| {
let start = datetime.now();
self.requestCount += 1;
// Nach der Response die Dauer messen
ctx.after_response(|| {
let duration = datetime.now() - start;
self.requestDurations.push(duration);
});
});
// Prometheus-Endpunkt registrieren
ctx.register_route("GET", "/metrics", || {
let avgDuration = self.requestDurations.avg();
return `
# HELP http_requests_total Total HTTP requests
# TYPE http_requests_total counter
http_requests_total ${self.requestCount}
# HELP http_request_duration_avg Average request duration
# TYPE http_request_duration_avg gauge
http_request_duration_avg ${avgDuration}
`;
});
log.info("Metrics Plugin aktiviert auf /metrics");
}
fn on_unload() {
log.info("Metrics Plugin deaktiviert");
}
}
pub fn create(config: Map<string, any>): Plugin {
return MetricsPlugin {};
}Plugin laden und konfigurieren
Plugins werden in der velin.toml aktiviert:
[plugins]
# Aus der Registry
metrics = { version = "1.0.0" }
# Lokales Plugin
my-custom = { path = "./plugins/my_plugin.vplugin" }
# Mit Konfiguration
auth-provider = {
version = "2.1.0",
config = { provider = "oauth2", clientId = "abc123" }
}Hot Reload
Plugins können zur Laufzeit neu geladen werden mit
velin plugin reload my-plugin.Plugin Context API
// Verfügbare Methoden im PluginContext
impl Plugin for MyPlugin {
fn on_load(ctx: PluginContext) {
// Hooks registrieren
ctx.register_hook("on_request", |req| { ... });
ctx.register_hook("on_error", |err| { ... });
// Eigene CLI-Befehle
ctx.register_command("my-cmd", || { ... });
// HTTP-Routen hinzufügen
ctx.register_route("GET", "/my-endpoint", || { ... });
ctx.register_route("POST", "/my-endpoint", |body| { ... });
// Konfiguration lesen
let apiKey = ctx.config.get("apiKey");
// Auf andere Services zugreifen
let db = ctx.get_service("database");
let cache = ctx.get_service("cache");
// Events emittieren
ctx.emit("my_plugin:initialized", { timestamp: datetime.now() });
// Auf Events lauschen
ctx.on("user:created", |user| {
log.info("Neuer User: " + user.email);
});
}
}Plugin bauen und veröffentlichen
# Plugin kompilieren
velin build --plugin my_plugin.velin
# Output: my_plugin.vplugin
# Lokales Testen
velin run --plugin ./my_plugin.vplugin
# In Registry veröffentlichen
velin publish --pluginBest Practices
Cleanup in on_unload
Ressourcen freigeben, Connections schließen
Fehler abfangen
Plugin-Fehler dürfen Host nicht crashen
Konfiguration validieren
Fehlende Config früh erkennen
Versionierung
Semantic Versioning für Kompatibilität