From 3b1f4d60882b8bf8c5b318ff5dd683dfcb80afa4 Mon Sep 17 00:00:00 2001 From: Amogh-Bharadwaj Date: Tue, 31 Oct 2023 14:02:08 -0700 Subject: [PATCH] drop mirror and more ui --- flow/generated/protos/route.pb.go | 39 +++++----- flow/generated/protos/route.pb.gw.go | 85 ++++++++++++++++++++++ protos/route.proto | 4 +- ui/app/api/mirrors/drop/route.ts | 30 ++++++++ ui/app/api/peers/route.ts | 99 +++++++++++++------------- ui/app/dto/MirrorsDTO.ts | 4 ++ ui/app/dto/PeersDTO.ts | 6 ++ ui/app/mirrors/edit/[mirrorId]/cdc.tsx | 1 + ui/app/mirrors/page.tsx | 16 +++-- ui/app/peers/[peerName]/datatables.tsx | 33 +++++++-- ui/app/peers/[peerName]/page.tsx | 26 +++++-- ui/components/DropDialog.tsx | 80 +++++++++++++++++++++ 12 files changed, 337 insertions(+), 86 deletions(-) create mode 100644 ui/app/api/mirrors/drop/route.ts create mode 100644 ui/components/DropDialog.tsx diff --git a/flow/generated/protos/route.pb.go b/flow/generated/protos/route.pb.go index f7522a60ab..f810724b74 100644 --- a/flow/generated/protos/route.pb.go +++ b/flow/generated/protos/route.pb.go @@ -1887,7 +1887,7 @@ var file_route_proto_rawDesc = []byte{ 0x50, 0x65, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x16, 0x0a, 0x12, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x44, 0x10, 0x01, 0x12, - 0x0a, 0x0a, 0x06, 0x46, 0x41, 0x49, 0x4c, 0x45, 0x44, 0x10, 0x02, 0x32, 0xa1, 0x0a, 0x0a, 0x0b, + 0x0a, 0x0a, 0x06, 0x46, 0x41, 0x49, 0x4c, 0x45, 0x44, 0x10, 0x02, 0x32, 0xbc, 0x0a, 0x0a, 0x0b, 0x46, 0x6c, 0x6f, 0x77, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x74, 0x0a, 0x0c, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x50, 0x65, 0x65, 0x72, 0x12, 0x21, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x64, 0x62, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, @@ -1957,28 +1957,29 @@ var file_route_proto_rawDesc = []byte{ 0x72, 0x53, 0x74, 0x61, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x23, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x12, 0x1b, 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x65, 0x65, 0x72, 0x73, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2f, 0x7b, 0x70, 0x65, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, - 0x65, 0x7d, 0x12, 0x4f, 0x0a, 0x0c, 0x53, 0x68, 0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x46, 0x6c, + 0x65, 0x7d, 0x12, 0x6a, 0x0a, 0x0c, 0x53, 0x68, 0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x46, 0x6c, 0x6f, 0x77, 0x12, 0x1d, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x64, 0x62, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x53, 0x68, 0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x64, 0x62, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x53, 0x68, 0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x00, 0x12, 0x7a, 0x0a, 0x0c, 0x4d, 0x69, 0x72, 0x72, 0x6f, 0x72, 0x53, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x12, 0x21, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x64, 0x62, 0x5f, 0x72, 0x6f, 0x75, - 0x74, 0x65, 0x2e, 0x4d, 0x69, 0x72, 0x72, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x64, 0x62, 0x5f, - 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x4d, 0x69, 0x72, 0x72, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x23, 0x82, 0xd3, 0xe4, 0x93, - 0x02, 0x1d, 0x12, 0x1b, 0x2f, 0x76, 0x31, 0x2f, 0x6d, 0x69, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x2f, - 0x7b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x6a, 0x6f, 0x62, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x7d, 0x42, - 0x7c, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x64, 0x62, 0x5f, 0x72, 0x6f, - 0x75, 0x74, 0x65, 0x42, 0x0a, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, - 0x01, 0x5a, 0x10, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2f, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x73, 0xa2, 0x02, 0x03, 0x50, 0x58, 0x58, 0xaa, 0x02, 0x0b, 0x50, 0x65, 0x65, 0x72, - 0x64, 0x62, 0x52, 0x6f, 0x75, 0x74, 0x65, 0xca, 0x02, 0x0b, 0x50, 0x65, 0x65, 0x72, 0x64, 0x62, - 0x52, 0x6f, 0x75, 0x74, 0x65, 0xe2, 0x02, 0x17, 0x50, 0x65, 0x65, 0x72, 0x64, 0x62, 0x52, 0x6f, - 0x75, 0x74, 0x65, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, - 0x02, 0x0b, 0x50, 0x65, 0x65, 0x72, 0x64, 0x62, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x62, 0x06, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x3a, 0x01, 0x2a, 0x22, 0x10, 0x2f, 0x76, + 0x31, 0x2f, 0x6d, 0x69, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x2f, 0x64, 0x72, 0x6f, 0x70, 0x12, 0x7a, + 0x0a, 0x0c, 0x4d, 0x69, 0x72, 0x72, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x21, + 0x2e, 0x70, 0x65, 0x65, 0x72, 0x64, 0x62, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x4d, 0x69, + 0x72, 0x72, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x22, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x64, 0x62, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, + 0x2e, 0x4d, 0x69, 0x72, 0x72, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x23, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x12, 0x1b, 0x2f, + 0x76, 0x31, 0x2f, 0x6d, 0x69, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x2f, 0x7b, 0x66, 0x6c, 0x6f, 0x77, + 0x5f, 0x6a, 0x6f, 0x62, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x7d, 0x42, 0x7c, 0x0a, 0x10, 0x63, 0x6f, + 0x6d, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x64, 0x62, 0x5f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x42, 0x0a, + 0x52, 0x6f, 0x75, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x10, 0x67, 0x65, + 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0xa2, 0x02, + 0x03, 0x50, 0x58, 0x58, 0xaa, 0x02, 0x0b, 0x50, 0x65, 0x65, 0x72, 0x64, 0x62, 0x52, 0x6f, 0x75, + 0x74, 0x65, 0xca, 0x02, 0x0b, 0x50, 0x65, 0x65, 0x72, 0x64, 0x62, 0x52, 0x6f, 0x75, 0x74, 0x65, + 0xe2, 0x02, 0x17, 0x50, 0x65, 0x65, 0x72, 0x64, 0x62, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x5c, 0x47, + 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x0b, 0x50, 0x65, 0x65, + 0x72, 0x64, 0x62, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/flow/generated/protos/route.pb.gw.go b/flow/generated/protos/route.pb.gw.go index b59aa82270..8f2266af94 100644 --- a/flow/generated/protos/route.pb.gw.go +++ b/flow/generated/protos/route.pb.gw.go @@ -379,6 +379,40 @@ func local_request_FlowService_GetStatInfo_0(ctx context.Context, marshaler runt } +func request_FlowService_ShutdownFlow_0(ctx context.Context, marshaler runtime.Marshaler, client FlowServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq ShutdownRequest + var metadata runtime.ServerMetadata + + newReader, berr := utilities.IOReaderFactory(req.Body) + if berr != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) + } + if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.ShutdownFlow(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_FlowService_ShutdownFlow_0(ctx context.Context, marshaler runtime.Marshaler, server FlowServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq ShutdownRequest + var metadata runtime.ServerMetadata + + newReader, berr := utilities.IOReaderFactory(req.Body) + if berr != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) + } + if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.ShutdownFlow(ctx, &protoReq) + return msg, metadata, err + +} + func request_FlowService_MirrorStatus_0(ctx context.Context, marshaler runtime.Marshaler, client FlowServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq MirrorStatusRequest var metadata runtime.ServerMetadata @@ -662,6 +696,31 @@ func RegisterFlowServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux }) + mux.Handle("POST", pattern_FlowService_ShutdownFlow_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + var err error + var annotatedContext context.Context + annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/peerdb_route.FlowService/ShutdownFlow", runtime.WithHTTPPathPattern("/v1/mirrors/drop")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_FlowService_ShutdownFlow_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + + forward_FlowService_ShutdownFlow_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + mux.Handle("GET", pattern_FlowService_MirrorStatus_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() @@ -926,6 +985,28 @@ func RegisterFlowServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux }) + mux.Handle("POST", pattern_FlowService_ShutdownFlow_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + var err error + var annotatedContext context.Context + annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/peerdb_route.FlowService/ShutdownFlow", runtime.WithHTTPPathPattern("/v1/mirrors/drop")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_FlowService_ShutdownFlow_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + + forward_FlowService_ShutdownFlow_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + mux.Handle("GET", pattern_FlowService_MirrorStatus_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() @@ -970,6 +1051,8 @@ var ( pattern_FlowService_GetStatInfo_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"v1", "peers", "stats", "peer_name"}, "")) + pattern_FlowService_ShutdownFlow_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "mirrors", "drop"}, "")) + pattern_FlowService_MirrorStatus_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2}, []string{"v1", "mirrors", "flow_job_name"}, "")) ) @@ -992,5 +1075,7 @@ var ( forward_FlowService_GetStatInfo_0 = runtime.ForwardResponseMessage + forward_FlowService_ShutdownFlow_0 = runtime.ForwardResponseMessage + forward_FlowService_MirrorStatus_0 = runtime.ForwardResponseMessage ) diff --git a/protos/route.proto b/protos/route.proto index 943c1b5c20..50caa3f6b2 100644 --- a/protos/route.proto +++ b/protos/route.proto @@ -209,7 +209,9 @@ service FlowService { rpc GetStatInfo(PostgresPeerActivityInfoRequest) returns (PeerStatResponse) { option (google.api.http) = { get: "/v1/peers/stats/{peer_name}" }; } - rpc ShutdownFlow(ShutdownRequest) returns (ShutdownResponse) {} + rpc ShutdownFlow(ShutdownRequest) returns (ShutdownResponse) { + option (google.api.http) = { post: "/v1/mirrors/drop", body: "*" }; + } rpc MirrorStatus(MirrorStatusRequest) returns (MirrorStatusResponse) { option (google.api.http) = { get: "/v1/mirrors/{flow_job_name}" }; } diff --git a/ui/app/api/mirrors/drop/route.ts b/ui/app/api/mirrors/drop/route.ts new file mode 100644 index 0000000000..07c2db0d96 --- /dev/null +++ b/ui/app/api/mirrors/drop/route.ts @@ -0,0 +1,30 @@ +import { UDropMirrorResponse } from '@/app/dto/MirrorsDTO'; +import { ShutdownRequest, ShutdownResponse } from '@/grpc_generated/route'; +import { GetFlowHttpAddressFromEnv } from '@/rpc/http'; + +export async function POST(request: Request) { + const body = await request.json(); + const { workflowId, flowJobName, sourcePeer, destinationPeer } = body; + const flowServiceAddr = GetFlowHttpAddressFromEnv(); + const req: ShutdownRequest = { + workflowId, + flowJobName, + sourcePeer, + destinationPeer, + }; + console.log('/drop/mirror: req:', req); + const dropStatus: ShutdownResponse = await fetch( + `${flowServiceAddr}/v1/mirrors/drop`, + { + method: 'POST', + body: JSON.stringify(req), + } + ).then((res) => { + return res.json(); + }); + let response: UDropMirrorResponse = { + dropped: dropStatus.ok, + }; + + return new Response(JSON.stringify(response)); +} diff --git a/ui/app/api/peers/route.ts b/ui/app/api/peers/route.ts index 29c687e0fc..dc1292c98f 100644 --- a/ui/app/api/peers/route.ts +++ b/ui/app/api/peers/route.ts @@ -1,4 +1,5 @@ import { + CatalogPeer, PeerConfig, UCreatePeerResponse, UValidatePeerResponse, @@ -94,56 +95,58 @@ export async function POST(request: Request) { } } +export const getTruePeer = (peer: CatalogPeer) => { + const newPeer: Peer = { + name: peer.name, + type: peer.type, + }; + const options = peer.options; + let config: + | BigqueryConfig + | SnowflakeConfig + | PostgresConfig + | EventHubConfig + | S3Config + | SqlServerConfig + | EventHubGroupConfig; + switch (peer.type) { + case 0: + config = BigqueryConfig.decode(options); + newPeer.bigqueryConfig = config; + break; + case 1: + config = SnowflakeConfig.decode(options); + newPeer.snowflakeConfig = config; + break; + case 3: + config = PostgresConfig.decode(options); + newPeer.postgresConfig = config; + break; + case 4: + config = EventHubConfig.decode(options); + newPeer.eventhubConfig = config; + break; + case 5: + config = S3Config.decode(options); + newPeer.s3Config = config; + break; + case 6: + config = SqlServerConfig.decode(options); + newPeer.sqlserverConfig = config; + break; + case 7: + config = EventHubGroupConfig.decode(options); + newPeer.eventhubGroupConfig = config; + break; + default: + return newPeer; + } + return newPeer; +}; + // GET all the peers from the database export async function GET(request: Request) { const peers = await prisma.peers.findMany(); - const truePeers: Peer[] = peers.map((peer) => { - const newPeer: Peer = { - name: peer.name, - type: peer.type, - }; - const options = peer.options; - let config: - | BigqueryConfig - | SnowflakeConfig - | PostgresConfig - | EventHubConfig - | S3Config - | SqlServerConfig - | EventHubGroupConfig; - switch (peer.type) { - case 0: - config = BigqueryConfig.decode(options); - newPeer.bigqueryConfig = config; - break; - case 1: - config = SnowflakeConfig.decode(options); - newPeer.snowflakeConfig = config; - break; - case 3: - config = PostgresConfig.decode(options); - newPeer.postgresConfig = config; - break; - case 4: - config = EventHubConfig.decode(options); - newPeer.eventhubConfig = config; - break; - case 5: - config = S3Config.decode(options); - newPeer.s3Config = config; - break; - case 6: - config = SqlServerConfig.decode(options); - newPeer.sqlserverConfig = config; - break; - case 7: - config = EventHubGroupConfig.decode(options); - newPeer.eventhubGroupConfig = config; - break; - default: - return newPeer; - } - return newPeer; - }); + const truePeers: Peer[] = peers.map((peer) => getTruePeer(peer)); return new Response(JSON.stringify(truePeers)); } diff --git a/ui/app/dto/MirrorsDTO.ts b/ui/app/dto/MirrorsDTO.ts index 6da4ace573..7029c55902 100644 --- a/ui/app/dto/MirrorsDTO.ts +++ b/ui/app/dto/MirrorsDTO.ts @@ -5,6 +5,10 @@ export type UCreateMirrorResponse = { created: boolean; }; +export type UDropMirrorResponse = { + dropped: boolean; +}; + export type CDCConfig = FlowConnectionConfigs; export type MirrorConfig = CDCConfig | QRepConfig; export type MirrorSetter = Dispatch>; diff --git a/ui/app/dto/PeersDTO.ts b/ui/app/dto/PeersDTO.ts index 44bd4bace8..43b6d14671 100644 --- a/ui/app/dto/PeersDTO.ts +++ b/ui/app/dto/PeersDTO.ts @@ -23,3 +23,9 @@ export type UColumnsResponse = { }; export type PeerConfig = PostgresConfig | SnowflakeConfig; +export type CatalogPeer = { + id: number; + name: string; + type: number; + options: Buffer; +}; diff --git a/ui/app/mirrors/edit/[mirrorId]/cdc.tsx b/ui/app/mirrors/edit/[mirrorId]/cdc.tsx index 02202922cc..a1f515d947 100644 --- a/ui/app/mirrors/edit/[mirrorId]/cdc.tsx +++ b/ui/app/mirrors/edit/[mirrorId]/cdc.tsx @@ -195,6 +195,7 @@ export function CDCMirror({ cdc, syncStatusChild }: CDCMirrorStatusProps) { className='flex flex-col w-full' defaultValue={selectedTab} onValueChange={setSelectedTab} + style={{ marginTop: '2rem' }} > Source Destination Start Time - Status + } > @@ -94,10 +96,12 @@ async function CDCFlows() { - - - Active - + ))} @@ -152,7 +156,7 @@ async function QRepFlows() { Source Destination Start Time - Status + } > diff --git a/ui/app/peers/[peerName]/datatables.tsx b/ui/app/peers/[peerName]/datatables.tsx index 12aa77715a..a9f5d9d46d 100644 --- a/ui/app/peers/[peerName]/datatables.tsx +++ b/ui/app/peers/[peerName]/datatables.tsx @@ -1,15 +1,25 @@ import { CopyButton } from '@/components/CopyButton'; import { SlotInfo, StatInfo } from '@/grpc_generated/route'; +import { Label } from '@/lib/Label'; import { Table, TableCell, TableRow } from '@/lib/Table'; import { DurationDisplay, SlotNameDisplay } from './helpers'; export const SlotTable = ({ data }: { data: SlotInfo[] }) => { return ( -
-
+
+
-
+ +
@@ -43,10 +53,19 @@ export const SlotTable = ({ data }: { data: SlotInfo[] }) => { export const StatTable = ({ data }: { data: StatInfo[] }) => { return (
-
+
-
+ +
diff --git a/ui/app/peers/[peerName]/page.tsx b/ui/app/peers/[peerName]/page.tsx index e833a37cc5..3fcf4ce36f 100644 --- a/ui/app/peers/[peerName]/page.tsx +++ b/ui/app/peers/[peerName]/page.tsx @@ -1,6 +1,8 @@ import ReloadButton from '@/components/ReloadButton'; import { PeerSlotResponse, PeerStatResponse } from '@/grpc_generated/route'; +import { Label } from '@/lib/Label'; import { GetFlowHttpAddressFromEnv } from '@/rpc/http'; +import Link from 'next/link'; import { SlotTable, StatTable } from './datatables'; export const dynamic = 'force-dynamic'; @@ -43,17 +45,31 @@ const PeerData = async ({ params: { peerName } }: DataConfigProps) => { style={{ display: 'flex', flexDirection: 'column', - height: '80vh', + justifyContent: 'space-between', + height: '70vh', }} > ) : ( -
- We do not have stats to show for this peer at the moment. Please note - that peer replication slot information and stat activity is currently - only supported for PostgreSQL peers. +
+ We do not have stats to show for this peer at the moment. Please check + if your PostgreSQL peer is open for connections. Note that peer + replication slot information and stat activity is currently only + supported for PostgreSQL peers. +
)}
diff --git a/ui/components/DropDialog.tsx b/ui/components/DropDialog.tsx new file mode 100644 index 0000000000..1b437217b3 --- /dev/null +++ b/ui/components/DropDialog.tsx @@ -0,0 +1,80 @@ +'use client'; +import { UDropMirrorResponse } from '@/app/dto/MirrorsDTO'; +import { Peer } from '@/grpc_generated/peers'; +import { Button } from '@/lib/Button'; +import { Dialog, DialogClose } from '@/lib/Dialog'; +import { Icon } from '@/lib/Icon'; +import { Label } from '@/lib/Label'; +import { Divider } from '@tremor/react'; +import { useState } from 'react'; +import { BarLoader } from 'react-spinners'; + +export const DropDialog = (dropArgs: { + workflowId: string | null; + flowJobName: string; + sourcePeer: Peer; + destinationPeer: Peer; +}) => { + const [loading, setLoading] = useState(false); + const [msg, setMsg] = useState(''); + const handleDrop = async () => { + if (!dropArgs.workflowId) { + setMsg('Workflow ID not found for this mirror.'); + return; + } + + setLoading(true); + const dropRes: UDropMirrorResponse = await fetch('api/mirrors/drop', { + method: 'POST', + body: JSON.stringify(dropArgs), + }).then((res) => res.json()); + setLoading(false); + if (dropRes.dropped !== true) + setMsg('Something went wrong when trying to drop the mirror.'); + }; + + return ( + + + + } + > +
+ + + +
+ + + + +
+ {msg && ( + + )} +
+
+ ); +};