From 1d42fa7c3145006f6a1623e4031440fd615491f0 Mon Sep 17 00:00:00 2001 From: goflutterjava Date: Tue, 7 Dec 2021 18:13:28 +0800 Subject: [PATCH] Support namespace backlog quota --- lib/api/pulsar/pulsar_namespace_api.dart | 34 ++++++ lib/module/pulsar/pulsar_namespace.dart | 32 +++++ lib/ui/pulsar/pulsar_instance.dart | 8 +- lib/ui/pulsar/screen/pulsar_namespace.dart | 10 +- .../pulsar/widget/pulsar_message_query.dart | 12 -- .../pulsar_namespace_backlog_quota.dart | 111 ++++++++++++++++++ ...ar_namespace_backlog_quota_view_model.dart | 78 ++++++++++++ macos/Podfile.lock | 2 +- 8 files changed, 266 insertions(+), 21 deletions(-) delete mode 100644 lib/ui/pulsar/widget/pulsar_message_query.dart create mode 100644 lib/ui/pulsar/widget/pulsar_namespace_backlog_quota.dart create mode 100644 lib/vm/pulsar/pulsar_namespace_backlog_quota_view_model.dart diff --git a/lib/api/pulsar/pulsar_namespace_api.dart b/lib/api/pulsar/pulsar_namespace_api.dart index 637b7f5..48925e0 100644 --- a/lib/api/pulsar/pulsar_namespace_api.dart +++ b/lib/api/pulsar/pulsar_namespace_api.dart @@ -40,4 +40,38 @@ class PulsarNamespaceApi { .toList(); } + static Future getBacklogQuota(String host, int port, String tenant, + String namespace) async { + String url = + 'http://$host:${port.toString()}/admin/v2/namespaces/$tenant/$namespace/backlogQuotaMap'; + var response = await http.get(Uri.parse(url), + headers: { + 'Content-Type': 'application/json; charset=UTF-8', + }); + if (HttpUtil.abnormal(response.statusCode)) { + log('ErrorCode is ${response.statusCode}, body is ${response.body}'); + throw Exception( + 'ErrorCode is ${response.statusCode}, body is ${response.body}'); + } + Map jsonResponse = json.decode(response.body) as Map; + return BacklogQuotaResp.fromJson(jsonResponse["destination_storage"]); + } + + static Future updateBacklogQuota(String host, int port, String tenant, + String namespace, int limit, int? limitTime, String policy) async { + String url = + 'http://$host:${port.toString()}/admin/v2/namespaces/$tenant/$namespace/backlogQuota'; + BacklogQuotaReq backlogQuotaReq = new BacklogQuotaReq(limit, limitTime, policy); + var response = await http.post(Uri.parse(url), + headers: { + 'Content-Type': 'application/json; charset=UTF-8', + }, + body: json.encode(backlogQuotaReq)); + if (HttpUtil.abnormal(response.statusCode)) { + log('ErrorCode is ${response.statusCode}, body is ${response.body}'); + throw Exception( + 'ErrorCode is ${response.statusCode}, body is ${response.body}'); + } + } + } diff --git a/lib/module/pulsar/pulsar_namespace.dart b/lib/module/pulsar/pulsar_namespace.dart index 46a1840..5111bba 100644 --- a/lib/module/pulsar/pulsar_namespace.dart +++ b/lib/module/pulsar/pulsar_namespace.dart @@ -12,3 +12,35 @@ class NamespaceResp { return NamespaceResp(split[split.length - 1]); } } + +class BacklogQuotaReq { + final int limitSize; + final int? limitTime; + final String policy; + + BacklogQuotaReq(this.limitSize, this.limitTime, this.policy); + + Map toJson() { + Map map = new Map(); + map["limitSize"] = this.limitSize; + if (limitTime != null) { + map["limitTime"] = this.limitTime!; + } + map["policy"] = this.policy; + return map; + } +} + +class BacklogQuotaResp { + final int? limitSize; + final int? limitTime; + final String? policy; + + BacklogQuotaResp(this.limitSize, this.limitTime, this.policy); + + factory BacklogQuotaResp.fromJson(Map map) { + return BacklogQuotaResp(map["limitSize"], map["limitTime"], map["policy"]); + } +} + + diff --git a/lib/ui/pulsar/pulsar_instance.dart b/lib/ui/pulsar/pulsar_instance.dart index 2fc9a24..a3a0771 100644 --- a/lib/ui/pulsar/pulsar_instance.dart +++ b/lib/ui/pulsar/pulsar_instance.dart @@ -1,7 +1,6 @@ import 'package:flutter/material.dart'; import 'package:paas_dashboard_flutter/ui/pulsar/widget/pulsar_basic.dart'; import 'package:paas_dashboard_flutter/ui/pulsar/widget/pulsar_details.dart'; -import 'package:paas_dashboard_flutter/ui/pulsar/widget/pulsar_message_query.dart'; import 'package:paas_dashboard_flutter/vm/pulsar/pulsar_cluster_view_model.dart'; import 'package:paas_dashboard_flutter/vm/pulsar/pulsar_instance_view_model.dart'; import 'package:provider/provider.dart'; @@ -22,7 +21,7 @@ class _PulsarInstanceState extends State { Widget build(BuildContext context) { final vm = Provider.of(context); return DefaultTabController( - length: 3, + length: 2, child: Scaffold( appBar: AppBar( title: Text('Pulsar ${vm.name} Dashboard'), @@ -32,7 +31,6 @@ class _PulsarInstanceState extends State { text: "Basic", ), Tab(text: "Details"), - Tab(text: "MessageQuery"), ], ), ), @@ -47,10 +45,6 @@ class _PulsarInstanceState extends State { create: (context) => vm.deepCopy(), child: PulsarTenantsWidget(), ).build(context), - ChangeNotifierProvider( - create: (context) => vm.deepCopy(), - child: PulsarMessageQueryWidget(), - ).build(context), ], ), ), diff --git a/lib/ui/pulsar/screen/pulsar_namespace.dart b/lib/ui/pulsar/screen/pulsar_namespace.dart index 415a613..1858e2f 100644 --- a/lib/ui/pulsar/screen/pulsar_namespace.dart +++ b/lib/ui/pulsar/screen/pulsar_namespace.dart @@ -1,8 +1,10 @@ import 'package:flutter/material.dart'; +import 'package:paas_dashboard_flutter/ui/pulsar/widget/pulsar_namespace_backlog_quota.dart'; import 'package:paas_dashboard_flutter/ui/pulsar/widget/pulsar_partitioned_topic_list.dart'; import 'package:paas_dashboard_flutter/ui/pulsar/widget/pulsar_sink_list.dart'; import 'package:paas_dashboard_flutter/ui/pulsar/widget/pulsar_source_list.dart'; import 'package:paas_dashboard_flutter/ui/pulsar/widget/pulsar_topic_list.dart'; +import 'package:paas_dashboard_flutter/vm/pulsar/pulsar_namespace_backlog_quota_view_model.dart'; import 'package:paas_dashboard_flutter/vm/pulsar/pulsar_namespace_view_model.dart'; import 'package:paas_dashboard_flutter/vm/pulsar/pulsar_partitioned_topic_list_view_model.dart'; import 'package:paas_dashboard_flutter/vm/pulsar/pulsar_sink_list_view_model.dart'; @@ -34,13 +36,14 @@ class PulsarNamespaceScreenState extends State { Widget build(BuildContext context) { final vm = Provider.of(context); return DefaultTabController( - length: 4, + length: 5, child: Scaffold( appBar: AppBar( title: Text( 'Pulsar Namespace Tenant ${vm.tenant} -> Namespace ${vm.namespace}'), bottom: TabBar( tabs: [ + Tab(text: "BacklogQuota"), Tab(text: "PartitionedTopics"), Tab(text: "Topics"), Tab(text: "Source"), @@ -50,6 +53,11 @@ class PulsarNamespaceScreenState extends State { ), body: TabBarView( children: [ + ChangeNotifierProvider( + create: (context) => PulsarNamespaceBacklogQuotaViewModel( + vm.pulsarInstancePo, vm.tenantResp, vm.namespaceResp), + child: PulsarNamespaceBacklogQuotaWidget(), + ).build(context), ChangeNotifierProvider( create: (context) => PulsarPartitionedTopicListViewModel( vm.pulsarInstancePo, vm.tenantResp, vm.namespaceResp), diff --git a/lib/ui/pulsar/widget/pulsar_message_query.dart b/lib/ui/pulsar/widget/pulsar_message_query.dart deleted file mode 100644 index fbf7973..0000000 --- a/lib/ui/pulsar/widget/pulsar_message_query.dart +++ /dev/null @@ -1,12 +0,0 @@ -import 'package:flutter/material.dart'; - -class PulsarMessageQueryWidget extends StatelessWidget { - PulsarMessageQueryWidget(); - - @override - Widget build(BuildContext context) { - return ListView( - children: [], - ); - } -} diff --git a/lib/ui/pulsar/widget/pulsar_namespace_backlog_quota.dart b/lib/ui/pulsar/widget/pulsar_namespace_backlog_quota.dart new file mode 100644 index 0000000..f9833ae --- /dev/null +++ b/lib/ui/pulsar/widget/pulsar_namespace_backlog_quota.dart @@ -0,0 +1,111 @@ +import 'package:flutter/material.dart'; +import 'package:paas_dashboard_flutter/generated/l10n.dart'; +import 'package:paas_dashboard_flutter/ui/util/exception_util.dart'; +import 'package:paas_dashboard_flutter/ui/util/form_util.dart'; +import 'package:paas_dashboard_flutter/ui/util/spinner_util.dart'; +import 'package:paas_dashboard_flutter/vm/pulsar/pulsar_namespace_backlog_quota_view_model.dart'; +import 'package:provider/provider.dart'; + +class PulsarNamespaceBacklogQuotaWidget extends StatefulWidget { + PulsarNamespaceBacklogQuotaWidget(); + + @override + State createState() { + return new PulsarNamespaceBacklogQuotaWidgetState(); + } +} + +class PulsarNamespaceBacklogQuotaWidgetState extends State { + + @override + void initState() { + super.initState(); + final vm = Provider.of(context, listen: false); + vm.fetchBacklogQuota(); + } + + @override + void dispose() { + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final vm = Provider.of(context); + if (vm.loading) { + WidgetsBinding.instance!.addPostFrameCallback((timeStamp) { + SpinnerUtil.create(); + }); + } + ExceptionUtil.processLoadException(vm, context); + ExceptionUtil.processLoadException(vm, context); + var formButton = modifyBacklogQuotaButton(context); + var refreshButton = TextButton( + onPressed: () { + vm.fetchBacklogQuota(); + }, + child: Text(S.of(context).refresh)); + var body = ListView( + children: [ + Container( + height: 50, + child: ListView( + scrollDirection: Axis.horizontal, + shrinkWrap: true, + children: [refreshButton, formButton], + ), + ), + Container( + height: 50, + child: ListView( + scrollDirection: Axis.horizontal, + shrinkWrap: true, + children: [ + Text( + 'LimitSize is ${vm.limitSize}', + style: new TextStyle(fontSize: 20), + ), + ], + ), + ), + Container( + height: 50, + child: ListView( + scrollDirection: Axis.horizontal, + shrinkWrap: true, + children: [ + Text( + 'LimitTime is ${vm.limitTime}', + style: new TextStyle(fontSize: 20), + ), + ], + ), + ), + Container( + height: 50, + child: ListView( + scrollDirection: Axis.horizontal, + shrinkWrap: true, + children: [ + Text( + 'Policy is ${vm.retentionPolicy}', + style: new TextStyle(fontSize: 20), + ), + ], + ), + ), + ], + ); + return body; + } + + ButtonStyleButton modifyBacklogQuotaButton(BuildContext context) { + var list = [FormFieldDef('New Limit Size'), FormFieldDef('New Limit Time'), FormFieldDef('New Policy')]; + return FormUtil.updateButton3("New Backlog Quota", list, context, + (limitSize, limitTime, policy) async { + final vm = Provider.of(context, + listen: false); + vm.updateBacklogQuota(limitSize, limitTime, policy); + }); + } +} diff --git a/lib/vm/pulsar/pulsar_namespace_backlog_quota_view_model.dart b/lib/vm/pulsar/pulsar_namespace_backlog_quota_view_model.dart new file mode 100644 index 0000000..30a4fc4 --- /dev/null +++ b/lib/vm/pulsar/pulsar_namespace_backlog_quota_view_model.dart @@ -0,0 +1,78 @@ +import 'package:paas_dashboard_flutter/api/pulsar/pulsar_namespace_api.dart'; +import 'package:paas_dashboard_flutter/module/pulsar/pulsar_namespace.dart'; +import 'package:paas_dashboard_flutter/module/pulsar/pulsar_tenant.dart'; +import 'package:paas_dashboard_flutter/persistent/po/pulsar_instance_po.dart'; +import 'package:paas_dashboard_flutter/vm/base_load_view_model.dart'; + +class PulsarNamespaceBacklogQuotaViewModel extends BaseLoadViewModel { + final PulsarInstancePo pulsarInstancePo; + final TenantResp tenantResp; + final NamespaceResp namespaceResp; + int limitSize = -1; + int limitTime = -1; + String retentionPolicy = "unset"; + + PulsarNamespaceBacklogQuotaViewModel( + this.pulsarInstancePo, this.tenantResp, this.namespaceResp); + + PulsarNamespaceBacklogQuotaViewModel deepCopy() { + return new PulsarNamespaceBacklogQuotaViewModel(pulsarInstancePo.deepCopy(), + tenantResp.deepCopy(), namespaceResp.deepCopy()); + } + + int get id { + return this.pulsarInstancePo.id; + } + + String get name { + return this.pulsarInstancePo.name; + } + + String get host { + return this.pulsarInstancePo.host; + } + + int get port { + return this.pulsarInstancePo.port; + } + + String get tenant { + return this.tenantResp.tenant; + } + + String get namespace { + return this.namespaceResp.namespace; + } + + Future fetchBacklogQuota() async { + try { + final BacklogQuotaResp resp = await PulsarNamespaceApi.getBacklogQuota( + host, port, tenant, namespace); + this.limitSize = resp.limitSize == null ? -1 : resp.limitSize!; + this.limitTime = resp.limitTime == null ? -1 : resp.limitTime!; + this.retentionPolicy = resp.policy == null ? "null" : resp.policy!; + loadSuccess(); + } on Exception catch (e) { + loadException = e; + loading = false; + } + notifyListeners(); + } + + Future updateBacklogQuota( + String limit, String limitTime, String policy) async { + try { + if (limitTime == "") { + await PulsarNamespaceApi.updateBacklogQuota( + host, port, tenant, namespace, int.parse(limit), null, policy); + } else { + await PulsarNamespaceApi.updateBacklogQuota(host, port, tenant, + namespace, int.parse(limit), int.parse(limitTime), policy); + } + await fetchBacklogQuota(); + } on Exception catch (e) { + opException = e; + notifyListeners(); + } + } +} diff --git a/macos/Podfile.lock b/macos/Podfile.lock index 2b61683..f968896 100644 --- a/macos/Podfile.lock +++ b/macos/Podfile.lock @@ -28,4 +28,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: 6eac6b3292e5142cfc23bdeb71848a40ec51c14c -COCOAPODS: 1.10.2 +COCOAPODS: 1.11.2