Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Split flagged pieces page into flagged / flagged because unsealed #1509

Merged
merged 1 commit into from
Jun 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions gql/resolver_piece.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,20 @@ func (r *resolver) PiecesFlagged(ctx context.Context, args piecesFlaggedArgs) (*
}, nil
}

type piecesFlaggedCountArgs struct {
HasUnsealedCopy graphql.NullBool
}

func (r *resolver) PiecesFlaggedCount(ctx context.Context, args piecesFlaggedCountArgs) (int32, error) {
var filter *types.FlaggedPiecesListFilter
if args.HasUnsealedCopy.Set && args.HasUnsealedCopy.Value != nil {
filter = &types.FlaggedPiecesListFilter{HasUnsealedCopy: *args.HasUnsealedCopy.Value}
}

count, err := r.piecedirectory.FlaggedPiecesCount(ctx, filter)
return int32(count), err
}

func (r *resolver) PiecesWithPayloadCid(ctx context.Context, args struct{ PayloadCid string }) ([]string, error) {
payloadCid, err := cid.Parse(args.PayloadCid)
if err != nil {
Expand Down
3 changes: 3 additions & 0 deletions gql/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,9 @@ type RootQuery {
"""Get a list of pieces that have been flagged as having problems"""
piecesFlagged(hasUnsealedCopy: Boolean, cursor: BigInt, offset: Int, limit: Int): FlaggedPiecesList!

"""Get the number of pieces that have been flagged as having problems"""
piecesFlaggedCount(hasUnsealedCopy: Boolean): Int!

"""Get information about a piece from the piece store, DAG store and database"""
pieceStatus(pieceCid: String!): PieceStatus!

Expand Down
6 changes: 4 additions & 2 deletions react/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {LegacyDealDetail} from "./LegacyDealDetail"
import {SettingsPage} from "./Settings";
import {Banner} from "./Banner";
import {ProposalLogsPage} from "./ProposalLogs";
import {PieceDoctorPage, InspectPiecePage, LIDPage} from "./LID";
import {PieceDoctorPage, InspectPiecePage, LIDPage, NoUnsealedSectorPieces, NoUnsealedSectorPage} from "./LID";
import {RetrievalLogsPage} from "./RetrievalLogs";
import {RetrievalLogDetail} from "./RetrievalLogDetail";

Expand Down Expand Up @@ -56,9 +56,11 @@ function App(props) {
<Route path="/deals/:dealID" element={<DealDetail />} />
<Route path="/legacy-deals/:dealID" element={<LegacyDealDetail />} />
<Route path="/piece-doctor" element={<PieceDoctorPage />} />
<Route path="/piece-doctor/piece/:pieceCID" element={<InspectPiecePage />} />
<Route path="/piece-doctor/from/:cursor/page/:pageNum" element={<PieceDoctorPage />} />
<Route path="/piece-doctor/:query" element={<PieceDoctorPage />} />
<Route path="/piece-doctor/piece/:pieceCID" element={<InspectPiecePage />} />
<Route path="/no-unsealed" element={<NoUnsealedSectorPage />} />
<Route path="/no-unsealed/from/:cursor/page/:pageNum" element={<NoUnsealedSectorPage />} />
<Route path="/" element={<StorageDealsPage />} />
</Routes>
</div>
Expand Down
4 changes: 4 additions & 0 deletions react/src/LID.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
.nav-link {
margin-left: 1em;
}

.block-stats th {
text-align: left;
}
Expand Down
157 changes: 140 additions & 17 deletions react/src/LID.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {useMutation, useQuery} from "@apollo/react-hooks";
import {
LIDQuery,
FlaggedPiecesQuery, PieceBuildIndexMutation,
PieceStatusQuery, PiecesWithPayloadCidQuery, PiecesWithRootPayloadCidQuery
PieceStatusQuery, PiecesWithPayloadCidQuery, PiecesWithRootPayloadCidQuery, FlaggedPiecesCountQuery
} from "./gql";
import moment from "moment";
import {DebounceInput} from 'react-debounce-input';
Expand All @@ -21,6 +21,8 @@ import {Info, InfoListItem} from "./Info";
import {CumulativeBarChart, CumulativeBarLabels} from "./CumulativeBarChart";
import {addCommas, humanFileSize} from "./util";

const lidBasePath = '/piece-doctor'

export function LIDMenuItem(props) {
return (
<Link key="lid" className="menu-item" to={"/lid"}>
Expand Down Expand Up @@ -223,6 +225,7 @@ function FlaggedPieces({setSearchQuery}) {
cursor: queryCursor,
offset: listOffset,
limit: rowsPerPage,
hasUnsealedCopy: true,
},
fetchPolicy: 'network-only',
})
Expand Down Expand Up @@ -256,14 +259,17 @@ function FlaggedPieces({setSearchQuery}) {
}

return <div className="flagged-pieces">
<h3>Flagged pieces</h3>
<NoUnsealedSectorLink />

<h3>
Flagged pieces ({totalCount})
</h3>

<table>
<tbody>
<tr>
<th>Piece CID</th>
<th>Index</th>
<th>Unsealed Copy</th>
<th>Deals</th>
</tr>

Expand All @@ -281,34 +287,37 @@ function FlaggedPieces({setSearchQuery}) {
</div>
}

function FlaggedPieceRow({piece}) {
// Lookup the piece by piece CID.
// We do this asynchronously instead of as part of the list query so that
// checking for unseal status of each piece doesn't block the whole page.
const { loading, error, data } = useQuery(PieceStatusQuery, {
function NoUnsealedSectorLink() {
const {loading, error, data} = useQuery(FlaggedPiecesCountQuery, {
pollInterval: 10000,
variables: {
pieceCid: piece.PieceCid,
hasUnsealedCopy: false,
},
fetchPolicy: 'network-only',
})

var isUnsealedMsg
if (error) return <div>Error: {error.message}</div>
if (loading) {
isUnsealedMsg = '...'
} else if (error) {
isUnsealedMsg = error.Message
} else if (data && data.pieceStatus) {
const isUnsealed = hasUnsealedCopy(data.pieceStatus)
isUnsealedMsg = isUnsealed ? 'Yes' : 'No'
return <div>&nbsp;</div>
}

if (!data.piecesFlaggedCount) {
return null
}

return <div>
<Link className="nav-link" to="/no-unsealed">See {data.piecesFlaggedCount} pieces with no unsealed copy ➜</Link>
</div>
}

function FlaggedPieceRow({piece}) {
return <tr>
<td>
<Link to={"/piece-doctor/piece/"+piece.PieceCid}>
{piece.PieceCid}
</Link>
</td>
<td>{piece.IndexStatus.Status}</td>
<td>{isUnsealedMsg}</td>
<td>{piece.Deals.length}</td>
</tr>
}
Expand All @@ -322,6 +331,120 @@ function hasUnsealedCopy(piece) {
return false
}

export function NoUnsealedSectorPage(props) {
return <PageContainer title="Piece Doctor">
<NoUnsealedSectorPieces />
</PageContainer>
}

function NoUnsealedSectorPieces() {
const navigate = useNavigate()
const params = useParams()
const pageNum = (params.pageNum && parseInt(params.pageNum)) || 1

var [rowsPerPage, setRowsPerPage] = useState(RowsPerPage.load)
const onRowsPerPageChange = (e) => {
const val = parseInt(e.target.value)
RowsPerPage.save(val)
setRowsPerPage(val)
navigate(lidBasePath)
scrollTop()
}

// Fetch rows on this page
const listOffset = (pageNum-1) * rowsPerPage
const queryCursor = (pageNum === 1) ? null : params.cursor
const {loading, error, data} = useQuery(FlaggedPiecesQuery, {
pollInterval: 10000,
variables: {
cursor: queryCursor,
offset: listOffset,
limit: rowsPerPage,
hasUnsealedCopy: false,
},
fetchPolicy: 'network-only',
})

if (error) return <div>Error: {error.message + " - check connection to Boost server"}</div>
if (loading) return <div>Loading...</div>

var res = data.piecesFlagged
var rows = res.pieces
const totalCount = data.piecesFlagged.totalCount
const moreRows = data.piecesFlagged.more

if (!totalCount) {
return <div className="flagged-pieces-none">
Boost doctor did not find any pieces that were flagged because there is no unsealed copy of the sector
</div>
}

var cursor = params.cursor
if (pageNum === 1 && rows.length) {
cursor = rows[0].CreatedAt.getTime()
}

const paginationParams = {
basePath: '/no-unsealed',
cursor, pageNum, totalCount,
rowsPerPage: rowsPerPage,
moreRows: moreRows,
onRowsPerPageChange: onRowsPerPageChange,
onLinkClick: scrollTop,
}

return <div className="flagged-pieces inspect-content">
<FlaggedPiecesLink />

<h3>
Pieces with no unsealed sector ({totalCount})
</h3>

<table>
<tbody>
<tr>
<th>Piece CID</th>
<th>Index</th>
<th>Deals</th>
</tr>

{rows.map(piece => (
<FlaggedPieceRow
key={piece.Piece.PieceCid}
piece={piece.Piece}
/>
))}
</tbody>
</table>

<Pagination {...paginationParams} />
</div>
}

function FlaggedPiecesLink() {
const {loading, error, data} = useQuery(FlaggedPiecesCountQuery, {
pollInterval: 10000,
variables: {
hasUnsealedCopy: true,
},
fetchPolicy: 'network-only',
})

if (error) return <div>Error: {error.message}</div>
if (loading) {
return <div>&nbsp;</div>
}

if (!data.piecesFlaggedCount) {
return null
}

return <div>
<Link className="nav-link" to="/piece-doctor">See {data.piecesFlaggedCount} flagged pieces ➜</Link>
</div>
}


// Page showing information about a particular piece
export function InspectPiecePage(props) {
const params = useParams()
Expand Down
11 changes: 9 additions & 2 deletions react/src/gql.js
Original file line number Diff line number Diff line change
Expand Up @@ -398,8 +398,8 @@ const PiecesWithPayloadCidQuery = gql`
`;

const FlaggedPiecesQuery = gql`
query AppFlaggedPiecesQuery($cursor: BigInt, $offset: Int, $limit: Int) {
piecesFlagged(cursor: $cursor, offset: $offset, limit: $limit) {
query AppFlaggedPiecesQuery($hasUnsealedCopy: Boolean, $cursor: BigInt, $offset: Int, $limit: Int) {
piecesFlagged(hasUnsealedCopy: $hasUnsealedCopy, cursor: $cursor, offset: $offset, limit: $limit) {
pieces {
CreatedAt
Piece {
Expand All @@ -424,6 +424,12 @@ const FlaggedPiecesQuery = gql`
}
`;

const FlaggedPiecesCountQuery = gql`
query AppFlaggedPiecesCountQuery($hasUnsealedCopy: Boolean) {
piecesFlaggedCount(hasUnsealedCopy: $hasUnsealedCopy)
}
`;

const PieceBuildIndexMutation = gql`
mutation AppPieceBuildIndexMutation($pieceCid: String!) {
pieceBuildIndex(pieceCid: $pieceCid)
Expand Down Expand Up @@ -738,6 +744,7 @@ export {
PieceBuildIndexMutation,
PieceStatusQuery,
FlaggedPiecesQuery,
FlaggedPiecesCountQuery,
LIDQuery,
StorageQuery,
LegacyStorageQuery,
Expand Down