Files
dbx/apps/desktop/src/lib/mq-tauri.ts
T
miracleandt8y2 2a59d3143e feat(mq): implement Apache Pulsar message queue admin
* feat(mq): implement Apache Pulsar message queue admin

- Add complete MQ admin adapter layer with version detection
  * Pulsar adapter with multi-version API support
  * OAuth2 token caching and authentication
  * JWT token signing for Pulsar clients
  * Transport layer (SSH/Proxy) integration

- Implement comprehensive admin operations
  * Tenant, namespace, topic management
  * Subscription and consumer/producer monitoring
  * Rate limits, backlog quotas, retention policies
  * Permissions and role-based access control
  * Raw admin API for advanced operations

- Add desktop UI components
  * MQ admin console with tabbed interface
  * Tenant, namespace, topic panels
  * Subscription management and cursor operations
  * Monitoring panel with stats visualization
  * Policy configuration UI

- Add web routes for MQ admin operations
- Add secret store support for MQ auth credentials
- Add comprehensive test coverage

* fix: del local test files

* fix(mq): mark message queue as unsupported mcpMode in driver manifest

MQ admin connections do not use the MCP query bridge - they use a
separate REST admin API. Mark mcpMode as 'unsupported' to align with
the test expectations and reflect the actual architecture.

Fixes CI test: driver-manifest.test.ts

* fix(mq): fix TypeScript errors in MQ components

- Fix typo in SubscriptionsPanel.vue: messagformatError(e)Id -> message.messageId
- Use formatError() helper in RawApiPanel.vue instead of accessing e?.message
- Fix undefined 'tab' reference in ConnectionTree.vue: use config.db_type instead

Fixes frontend CI TypeScript check errors.

* fix(mcp): add 'mq' to MCP server connection type description

The MCP server's connection type description must include all database
types from the driver manifest. Add 'mq' to the list to fix the test:
'add connection database type description includes every manifest database type'

Fixes: packages/mcp-server/tests/driver-manifest.test.ts

* fix(mq): add missing ConnectionConfig fields for Rust compilation

- Add gbase_server and keepalive_interval_secs fields to all ConnectionConfig
  test constructors in mq/config.rs, mq/service.rs, and storage.rs
- Import uses_bare_mysql_pool in connection.rs tests module

Fixes compilation errors from upstream ConnectionConfig changes.

* chore(ui): simplify Pulsar icon to logo-only version

Remove text from Pulsar icon (127x30 -> 35x30), keeping only
the wave logo symbol for a cleaner, more consistent appearance
with other database icons.

* fix(mq): return removed pools from drain_connection_pools

---------

Co-authored-by: t8y2 <1156263951@qq.com>
2026-06-16 21:57:17 +08:00

205 lines
8.0 KiB
TypeScript

// Message queue admin API functions - Tauri invoke layer
import { invoke } from "@tauri-apps/api/core";
import type {
MqClusterInfo,
TenantInfo,
TenantConfig,
NamespaceRef,
NamespaceInfo,
NamespaceConfig,
TopicRef,
TopicInfo,
ListTopicsOpts,
TopicStats,
SubscriptionInfo,
ResetPosition,
SkipCount,
ConsumerInfo,
ProducerInfo,
PolicyScope,
PublishRate,
DispatchRate,
SubscribeRate,
BacklogQuota,
RetentionPolicy,
AuthAction,
PermissionMap,
MqTokenIssueRequest,
MqTokenRecord,
MqIssuedToken,
BacklogStats,
PeekedMessage,
MqRawRequest,
MqRawResponse,
} from "@/types/mq";
// Connectivity
export async function mqTestConnection(connectionId: string): Promise<MqClusterInfo> {
return invoke("mq_test_connection", { connectionId });
}
// Tenants
export async function mqListTenants(connectionId: string): Promise<TenantInfo[]> {
return invoke("mq_list_tenants", { connectionId });
}
export async function mqGetTenant(connectionId: string, name: string): Promise<TenantInfo> {
return invoke("mq_get_tenant", { connectionId, name });
}
export async function mqCreateTenant(connectionId: string, name: string, config: TenantConfig): Promise<void> {
return invoke("mq_create_tenant", { connectionId, name, config });
}
export async function mqUpdateTenant(connectionId: string, name: string, config: TenantConfig): Promise<void> {
return invoke("mq_update_tenant", { connectionId, name, config });
}
export async function mqDeleteTenant(connectionId: string, name: string, force: boolean): Promise<void> {
return invoke("mq_delete_tenant", { connectionId, name, force });
}
// Namespaces
export async function mqListNamespaces(connectionId: string, tenant: string): Promise<NamespaceInfo[]> {
return invoke("mq_list_namespaces", { connectionId, tenant });
}
export async function mqCreateNamespace(connectionId: string, ns: NamespaceRef, config: NamespaceConfig): Promise<void> {
return invoke("mq_create_namespace", { connectionId, ns, config });
}
export async function mqDeleteNamespace(connectionId: string, ns: NamespaceRef, force: boolean): Promise<void> {
return invoke("mq_delete_namespace", { connectionId, ns, force });
}
export async function mqGetNamespacePolicies(connectionId: string, ns: NamespaceRef): Promise<unknown> {
return invoke("mq_get_namespace_policies", { connectionId, ns });
}
// Topics
export async function mqListTopics(connectionId: string, ns: NamespaceRef, opts: ListTopicsOpts): Promise<TopicInfo[]> {
return invoke("mq_list_topics", { connectionId, ns, opts });
}
export async function mqCreateTopic(connectionId: string, topic: TopicRef, partitions?: number): Promise<void> {
return invoke("mq_create_topic", { connectionId, topic, partitions });
}
export async function mqDeleteTopic(connectionId: string, topic: TopicRef, force: boolean): Promise<void> {
return invoke("mq_delete_topic", { connectionId, topic, force });
}
export async function mqUpdatePartitions(connectionId: string, topic: TopicRef, partitions: number): Promise<void> {
return invoke("mq_update_partitions", { connectionId, topic, partitions });
}
export async function mqGetTopicStats(connectionId: string, topic: TopicRef): Promise<TopicStats> {
return invoke("mq_get_topic_stats", { connectionId, topic });
}
export async function mqGetTopicInternalStats(connectionId: string, topic: TopicRef): Promise<unknown> {
return invoke("mq_get_topic_internal_stats", { connectionId, topic });
}
// Subscriptions
export async function mqListSubscriptions(connectionId: string, topic: TopicRef): Promise<SubscriptionInfo[]> {
return invoke("mq_list_subscriptions", { connectionId, topic });
}
export async function mqCreateSubscription(connectionId: string, topic: TopicRef, sub: string, pos: ResetPosition): Promise<void> {
return invoke("mq_create_subscription", { connectionId, topic, sub, pos });
}
export async function mqDeleteSubscription(connectionId: string, topic: TopicRef, sub: string, force: boolean): Promise<void> {
return invoke("mq_delete_subscription", { connectionId, topic, sub, force });
}
export async function mqSkipMessages(connectionId: string, topic: TopicRef, sub: string, count: SkipCount): Promise<void> {
return invoke("mq_skip_messages", { connectionId, topic, sub, count });
}
export async function mqResetCursor(connectionId: string, topic: TopicRef, sub: string, pos: ResetPosition): Promise<void> {
return invoke("mq_reset_cursor", { connectionId, topic, sub, pos });
}
export async function mqClearBacklog(connectionId: string, topic: TopicRef, sub: string): Promise<void> {
return invoke("mq_clear_backlog", { connectionId, topic, sub });
}
export async function mqPeekMessages(connectionId: string, topic: TopicRef, sub: string, count: number): Promise<PeekedMessage[]> {
return invoke("mq_peek_messages", { connectionId, topic, sub, count });
}
export async function mqExpireMessages(connectionId: string, topic: TopicRef, sub: string, expireSeconds: number): Promise<void> {
return invoke("mq_expire_messages", { connectionId, topic, sub, expireSeconds });
}
// Producers / Consumers
export async function mqListProducers(connectionId: string, topic: TopicRef): Promise<ProducerInfo[]> {
return invoke("mq_list_producers", { connectionId, topic });
}
export async function mqListConsumers(connectionId: string, topic: TopicRef, sub: string): Promise<ConsumerInfo[]> {
return invoke("mq_list_consumers", { connectionId, topic, sub });
}
export async function mqUnloadTopic(connectionId: string, topic: TopicRef): Promise<void> {
return invoke("mq_unload_topic", { connectionId, topic });
}
// Policies
export async function mqSetPublishRate(connectionId: string, scope: PolicyScope, rate: PublishRate): Promise<void> {
return invoke("mq_set_publish_rate", { connectionId, scope, rate });
}
export async function mqSetDispatchRate(connectionId: string, scope: PolicyScope, rate: DispatchRate): Promise<void> {
return invoke("mq_set_dispatch_rate", { connectionId, scope, rate });
}
export async function mqSetSubscribeRate(connectionId: string, scope: PolicyScope, rate: SubscribeRate): Promise<void> {
return invoke("mq_set_subscribe_rate", { connectionId, scope, rate });
}
export async function mqSetBacklogQuota(connectionId: string, scope: PolicyScope, quota: BacklogQuota): Promise<void> {
return invoke("mq_set_backlog_quota", { connectionId, scope, quota });
}
export async function mqSetRetention(connectionId: string, scope: PolicyScope, retention: RetentionPolicy): Promise<void> {
return invoke("mq_set_retention", { connectionId, scope, retention });
}
export async function mqGetEffectivePolicies(connectionId: string, scope: PolicyScope): Promise<unknown> {
return invoke("mq_get_effective_policies", { connectionId, scope });
}
// Permissions
export async function mqGrantPermission(connectionId: string, scope: PolicyScope, role: string, actions: AuthAction[]): Promise<void> {
return invoke("mq_grant_permission", { connectionId, scope, role, actions });
}
export async function mqRevokePermission(connectionId: string, scope: PolicyScope, role: string): Promise<void> {
return invoke("mq_revoke_permission", { connectionId, scope, role });
}
export async function mqListPermissions(connectionId: string, scope: PolicyScope): Promise<PermissionMap> {
return invoke("mq_list_permissions", { connectionId, scope });
}
export async function mqIssueToken(connectionId: string, req: MqTokenIssueRequest): Promise<MqIssuedToken> {
return invoke("mq_issue_token", { connectionId, req });
}
export async function mqListTokenRecords(connectionId: string, subject?: string): Promise<MqTokenRecord[]> {
return invoke("mq_list_token_records", { connectionId, subject });
}
// Monitoring
export async function mqGetBacklog(connectionId: string, topic: TopicRef, sub?: string): Promise<BacklogStats> {
return invoke("mq_get_backlog", { connectionId, topic, sub });
}
// Raw request
export async function mqRawRequest(connectionId: string, req: MqRawRequest): Promise<MqRawResponse> {
return invoke("mq_raw_request", { connectionId, req });
}