Skip to content

Commit

Permalink
feat: split flagged pieces page into flagged / flagged because unsealed
Browse files Browse the repository at this point in the history
  • Loading branch information
dirkmc committed Jun 9, 2023
1 parent 54edf11 commit cc241f3
Show file tree
Hide file tree
Showing 6 changed files with 172 additions and 21 deletions.
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
155 changes: 138 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 Down Expand Up @@ -225,6 +225,7 @@ function FlaggedPieces({setSearchQuery}) {
cursor: queryCursor,
offset: listOffset,
limit: rowsPerPage,
hasUnsealedCopy: true,
},
fetchPolicy: 'network-only',
})
Expand Down Expand Up @@ -258,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 @@ -283,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 @@ -324,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

0 comments on commit cc241f3

Please sign in to comment.