Skip to content
This repository was archived by the owner on Jan 7, 2026. It is now read-only.
Closed
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
36 changes: 18 additions & 18 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -1,27 +1,27 @@
version: 2
updates:
- package-ecosystem: "npm"
directory: "/"
- package-ecosystem: 'npm'
directory: '/'
versioning-strategy: increase
schedule:
interval: "daily"
time: "09:00"
timezone: "Europe/Berlin"
interval: 'daily'
time: '09:00'
timezone: 'Europe/Berlin'
commit-message:
prefix: "deps"
prefix-development: "deps(dev)"
- package-ecosystem: "github-actions"
directory: "/"
prefix: 'deps'
prefix-development: 'deps(dev)'
- package-ecosystem: 'github-actions'
directory: '/'
schedule:
interval: "daily"
time: "09:00"
timezone: "Europe/Berlin"
interval: 'daily'
time: '09:00'
timezone: 'Europe/Berlin'
commit-message:
prefix: "ci"
- package-ecosystem: "docker"
prefix: 'ci'
- package-ecosystem: 'docker'
directories:
- "/"
- '/'
schedule:
interval: "daily"
time: "15:00"
timezone: "Europe/Berlin"
interval: 'daily'
time: '15:00'
timezone: 'Europe/Berlin'
2 changes: 1 addition & 1 deletion .github/workflows/dependabot-auto-approve-always.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
id: metadata
uses: dependabot/fetch-metadata@v2
with:
github-token: "${{ secrets.GITHUB_TOKEN }}"
github-token: '${{ secrets.GITHUB_TOKEN }}'
- name: Approve a PR
if: ${{startsWith(steps.metadata.outputs.dependency-names, matrix.dependencyStartsWith)}}
run: gh pr review --approve "$PR_URL"
Expand Down
7 changes: 5 additions & 2 deletions .github/workflows/dependabot-auto-approve-minor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,12 @@ jobs:
id: metadata
uses: dependabot/fetch-metadata@v2
with:
github-token: "${{ secrets.GITHUB_TOKEN }}"
github-token: '${{ secrets.GITHUB_TOKEN }}'
- name: Approve a PR
if: ${{startsWith(steps.metadata.outputs.dependency-names, matrix.dependencyStartsWith) && (steps.metadata.outputs.update-type == 'version-update:semver-patch' || steps.metadata.outputs.update-type == 'version-update:semver-minor')}}
if:
${{startsWith(steps.metadata.outputs.dependency-names, matrix.dependencyStartsWith) &&
(steps.metadata.outputs.update-type == 'version-update:semver-patch' ||
steps.metadata.outputs.update-type == 'version-update:semver-minor')}}
run: gh pr review --approve "$PR_URL"
env:
PR_URL: ${{github.event.pull_request.html_url}}
Expand Down
7 changes: 0 additions & 7 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -1,9 +1,2 @@
# We are using https://standardjs.com coding style. It is unfortunately incompatible with Prettier;
# see https://github.com/standard/standard/issues/996 and the linked issues.
# Standard does not handle Markdown files though, so we want to use Prettier formatting.
# The goal of the configuration below is to configure Prettier to lint only Markdown files.
**/*.*
!**/*.md

# Let's keep LICENSE.md in the same formatting as we use in other PL repositories
LICENSE.md
2 changes: 0 additions & 2 deletions .prettierrc.yaml

This file was deleted.

15 changes: 7 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,26 @@ A lightweight IPNI node mapping Filecoin PieceCID → payload block CID.

## Basic use

Note: this will change soon, see
https://github.com/filecoin-station/piece-indexer/issues/33
Note: this will change soon, see https://github.com/filecoin-station/piece-indexer/issues/33

## `GET /sample/{provider-id}/{piece-cid}`

Sample a set of multihashes ingested by IPNI for a given ContextID, matching the
route eventually to be exposed by an IPNI reverse index.
Sample a set of multihashes ingested by IPNI for a given ContextID, matching the route eventually to
be exposed by an IPNI reverse index.

_This is an alternative implementation of the IPNI Reverse Index as specified in
[xedni/openapi.yaml](https://github.com/ipni/xedni/blob/526f90f5a6001cb50b52e6376f8877163f8018af/openapi.yaml)._

Parameters:

- `provider-id` - the peer ID of the storage provider (index publisher)
- `piece-cid` - the Filecoin deal's PieceCID as advertised by the provider in
Graphsync retrieval metadata
- `piece-cid` - the Filecoin deal's PieceCID as advertised by the provider in Graphsync retrieval
metadata

Response:

- `samples` - a list of exactly one payload block CID contained inside the piece
identified by the requested PieceCID.
- `samples` - a list of exactly one payload block CID contained inside the piece identified by the
requested PieceCID.

Example:

Expand Down
8 changes: 4 additions & 4 deletions api/bin/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const {
HOST = '127.0.0.1',
DOMAIN: domain = 'localhost',
REDIS_URL: redisUrl = 'redis://localhost:6379',
REQUEST_LOGGING: requestLogging = 'true'
REQUEST_LOGGING: requestLogging = 'true',
} = process.env

const redisUrlParsed = new URL(redisUrl)
Expand All @@ -19,7 +19,7 @@ const redis = new Redis({
username: redisUrlParsed.username,
password: redisUrlParsed.password,
lazyConnect: true, // call connect() explicitly so that we can exit on connection error
family: 6 // required for upstash
family: 6, // required for upstash
})

await redis.connect()
Expand All @@ -29,8 +29,8 @@ const app = createApp({
repository,
domain,
logger: {
level: ['1', 'true'].includes(requestLogging) ? 'info' : 'error'
}
level: ['1', 'true'].includes(requestLogging) ? 'info' : 'error',
},
})
console.log('Starting the http server on host %j port %s', HOST, PORT)
const baseUrl = await app.listen({ host: HOST, port: Number(PORT) })
Expand Down
18 changes: 12 additions & 6 deletions api/lib/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import Fastify from 'fastify'
/**
* @param {object} args
* @param {Repository} args.repository
* @param {string|boolean} args.domain
* @param {string | boolean} args.domain
* @param {Fastify.FastifyLoggerOptions} args.logger
*/
export function createApp ({ repository, domain, logger }) {
export function createApp({ repository, domain, logger }) {
const app = Fastify({ logger })
Sentry.setupFastifyErrorHandler(app)

Expand All @@ -21,11 +21,17 @@ export function createApp ({ repository, domain, logger }) {

app.get('/sample/:providerId/:pieceCid', async (request, reply) => {
const { providerId, pieceCid } = request.params
const payloadCids = await repository.getPiecePayloadBlocks(providerId, pieceCid)
const payloadCids = await repository.getPiecePayloadBlocks(
providerId,
pieceCid,
)
const body = {}
if (payloadCids.length) {
body.samples = payloadCids.slice(0, 1)
reply.header('cache-control', `public, max-age=${24 * 3600 /* 24 hours */}, immutable`)
reply.header(
'cache-control',
`public, max-age=${24 * 3600 /* 24 hours */}, immutable`,
)
} else {
body.error = 'PROVIDER_OR_PIECE_NOT_FOUND'
reply.header('cache-control', `public, max-age=${60 /* 1min */}`)
Expand All @@ -41,7 +47,7 @@ export function createApp ({ repository, domain, logger }) {
if (!walkerState) {
return reply.send({
providerId,
ingestionStatus: 'Unknown provider ID'
ingestionStatus: 'Unknown provider ID',
})
}

Expand All @@ -54,7 +60,7 @@ export function createApp ({ repository, domain, logger }) {
lastHeadWalkedFrom: walkerState.lastHead ?? walkerState.head,
adsMissingPieceCID: walkerState.adsMissingPieceCID ?? 0,
entriesNotRetrievable: walkerState.entriesNotRetrievable ?? 0,
piecesIndexed: await repository.countPiecesIndexed(providerId)
piecesIndexed: await repository.countPiecesIndexed(providerId),
})
})

Expand Down
15 changes: 5 additions & 10 deletions api/lib/instrument.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,9 @@ const { SENTRY_ENVIRONMENT = 'development' } = process.env

const pkg = JSON.parse(
await fs.readFile(
join(
dirname(fileURLToPath(import.meta.url)),
'..',
'..',
'package.json'
),
'utf8'
)
join(dirname(fileURLToPath(import.meta.url)), '..', '..', 'package.json'),
'utf8',
),
)

Sentry.init({
Expand All @@ -24,13 +19,13 @@ Sentry.init({
tracesSampleRate: 0.1,
// Ignore Fastify 4xx errors
// Remove once https://github.com/getsentry/sentry-javascript/pull/13198 lands
beforeSend (event, { originalException: err }) {
beforeSend(event, { originalException: err }) {
const isBadRequest =
typeof err === 'object' &&
err !== null &&
'statusCode' in err &&
typeof err.statusCode === 'number' &&
err.statusCode < 500
return isBadRequest ? null : event
}
},
})
13 changes: 5 additions & 8 deletions api/package.json
Original file line number Diff line number Diff line change
@@ -1,19 +1,16 @@
{
"name": "@filecoin-station/spark-piece-indexer-api",
"type": "module",
"private": true,
"type": "module",
"scripts": {
"start": "node bin/server.js",
"lint": "standard",
"start": "node bin/server.js",
"test": "node --test --test-reporter=spec"
},
"devDependencies": {
"standard": "^17.1.2"
},
"dependencies": {
"@filecoin-station/spark-piece-indexer-repository": "^1.0.0",
"@sentry/node": "^9.13.0",
"fastify": "^5.3.2",
"ioredis": "^5.6.1"
"@sentry/node": "^9.10.1",
"fastify": "^5.2.2",
"ioredis": "^5.6.0"
}
}
Loading