vitess.io/vitess@v0.16.2/web/vtadmin/src/components/routes/workflow/WorkflowStreams.tsx (about)

     1  /**
     2   * Copyright 2021 The Vitess Authors.
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  import { orderBy, groupBy } from 'lodash-es';
    18  import React, { useMemo } from 'react';
    19  import { Link } from 'react-router-dom';
    20  
    21  import { useWorkflow } from '../../../hooks/api';
    22  import { formatAlias } from '../../../util/tablets';
    23  import { formatDateTime } from '../../../util/time';
    24  import { getStreams, formatStreamKey, getStreamSource, getStreamTarget } from '../../../util/workflows';
    25  import { DataCell } from '../../dataTable/DataCell';
    26  import { DataTable } from '../../dataTable/DataTable';
    27  import { TabletLink } from '../../links/TabletLink';
    28  import { StreamStatePip } from '../../pips/StreamStatePip';
    29  import { WorkflowStreamsLagChart } from '../../charts/WorkflowStreamsLagChart';
    30  import { ShardLink } from '../../links/ShardLink';
    31  import { env } from '../../../util/env';
    32  
    33  interface Props {
    34      clusterID: string;
    35      keyspace: string;
    36      name: string;
    37  }
    38  
    39  const COLUMNS = ['Stream', 'Source', 'Target', 'Tablet'];
    40  
    41  export const WorkflowStreams = ({ clusterID, keyspace, name }: Props) => {
    42      const { data } = useWorkflow({ clusterID, keyspace, name });
    43  
    44      const streams = useMemo(() => {
    45          const rows = getStreams(data).map((stream) => ({
    46              key: formatStreamKey(stream),
    47              ...stream,
    48          }));
    49  
    50          return orderBy(rows, 'streamKey');
    51      }, [data]);
    52  
    53      const streamsByState = groupBy(streams, 'state');
    54  
    55      const renderRows = (rows: typeof streams) => {
    56          return rows.map((row) => {
    57              const href =
    58                  row.tablet && row.id
    59                      ? `/workflow/${clusterID}/${keyspace}/${name}/stream/${row.tablet.cell}/${row.tablet.uid}/${row.id}`
    60                      : null;
    61  
    62              const source = getStreamSource(row);
    63              const target = getStreamTarget(row, keyspace);
    64  
    65              return (
    66                  <tr key={row.key}>
    67                      <DataCell>
    68                          <StreamStatePip state={row.state} />{' '}
    69                          <Link className="font-bold" to={href}>
    70                              {row.key}
    71                          </Link>
    72                          <div className="text-sm text-secondary">
    73                              Updated {formatDateTime(row.time_updated?.seconds)}
    74                          </div>
    75                      </DataCell>
    76                      <DataCell>
    77                          {source ? (
    78                              <ShardLink
    79                                  clusterID={clusterID}
    80                                  keyspace={row.binlog_source?.keyspace}
    81                                  shard={row.binlog_source?.shard}
    82                              >
    83                                  {source}
    84                              </ShardLink>
    85                          ) : (
    86                              <span className="text-secondary">N/A</span>
    87                          )}
    88                      </DataCell>
    89                      <DataCell>
    90                          {target ? (
    91                              <ShardLink clusterID={clusterID} keyspace={keyspace} shard={row.shard}>
    92                                  {target}
    93                              </ShardLink>
    94                          ) : (
    95                              <span className="text-secondary">N/A</span>
    96                          )}
    97                      </DataCell>
    98                      <DataCell>
    99                          <TabletLink alias={formatAlias(row.tablet)} clusterID={clusterID}>
   100                              {formatAlias(row.tablet)}
   101                          </TabletLink>
   102                      </DataCell>
   103                  </tr>
   104              );
   105          });
   106      };
   107  
   108      return (
   109          <div className="mt-12 mb-16">
   110              {env().REACT_APP_ENABLE_EXPERIMENTAL_TABLET_DEBUG_VARS && (
   111                  <>
   112                      <h3 className="my-8">Stream VReplication Lag</h3>
   113                      <WorkflowStreamsLagChart clusterID={clusterID} keyspace={keyspace} workflowName={name} />
   114                  </>
   115              )}
   116  
   117              <h3 className="mt-24 mb-8">Streams</h3>
   118              {/* TODO(doeg): add a protobuf enum for this (https://github.com/vitessio/vitess/projects/12#card-60190340) */}
   119              {['Error', 'Copying', 'Running', 'Stopped'].map((streamState) => {
   120                  if (!Array.isArray(streamsByState[streamState])) {
   121                      return null;
   122                  }
   123  
   124                  return (
   125                      <div className="my-12" key={streamState}>
   126                          <DataTable
   127                              columns={COLUMNS}
   128                              data={streamsByState[streamState]}
   129                              // TODO(doeg): make pagination optional in DataTable https://github.com/vitessio/vitess/projects/12#card-60810231
   130                              pageSize={1000}
   131                              renderRows={renderRows}
   132                              title={streamState}
   133                          />
   134                      </div>
   135                  );
   136              })}
   137          </div>
   138      );
   139  };