Skip to content

Commit

Permalink
Remove the get speed command in favor of age state.
Browse files Browse the repository at this point in the history
  • Loading branch information
saul-jb committed Apr 10, 2024
1 parent 41354f5 commit 89c8512
Show file tree
Hide file tree
Showing 13 changed files with 39 additions and 167 deletions.
10 changes: 6 additions & 4 deletions packages/cli/src/commands/list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,9 @@ export const handler = createHandler<typeof builder>(async function * (argv) {
count: items.map(getState).filter(i => i.status === 'COMPLETED').length
}

const speeds = await argv.client.getSpeeds(items.map(i => i.cid), 5000)
const age = 5000
const ageState = await argv.client.getState(items.map(i => i.cid), { age })
const speeds = ageState.map(s => ({ cid: s.cid, speed: s.size / (age / 1000) }))

const getSpeed = ({ cid }: { cid: string }): number =>
speeds.find(s => s.cid === cid)?.speed ?? 0
Expand Down Expand Up @@ -129,12 +131,12 @@ export const handler = createHandler<typeof builder>(async function * (argv) {
for (const [key, subtree] of Object.entries(tree)) {
try {
const [item] = List.Return.parse([subtree])
const timeRemaining = Math.ceil((item.size - getState(item).size) / (getSpeed(item) * 1000))
const timeRemaining = Math.ceil((item.size - getState(item).size) / getSpeed(item))

yield [
`${' '.repeat(depth)}${key}`.slice(0, 18).padEnd(20),
`${formatSize(getState(item).size)}/${formatSize(item.size)} (${formatPercent(getState(item).size / item.size)})`.slice(0, 25).padEnd(27),
`${formatSize(getSpeed(item) * 1000)}/s ${isNaN(timeRemaining) ? '' : `(${timeRemaining} s)`}`.slice(0, 25).padEnd(27),
`${formatSize(getSpeed(item))}/s ${isNaN(timeRemaining) ? '' : `(${timeRemaining} s)`}`.slice(0, 25).padEnd(27),
`${getState(item).blocks}/${item.blocks} (${formatPercent(getState(item).blocks / item.blocks)})`.slice(0, 18).padEnd(20),
getState(item).status.slice(0, 13).padEnd(15),
`${item.priority}`.slice(0, 8).padEnd(10),
Expand Down Expand Up @@ -169,6 +171,6 @@ export const handler = createHandler<typeof builder>(async function * (argv) {
`${completed.count}/${total.count} (${formatPercent(completed.count / total.count)})`.slice(0, 13).padEnd(15),
`${formatSize(completed.size)}/${formatSize(total.size)} (${formatPercent(completed.size / total.size)})`.slice(0, 23).padEnd(25),
`${completed.blocks}/${total.blocks} (${formatPercent(completed.blocks / total.blocks)})`.slice(0, 18).padEnd(20),
`${formatSize(speeds.reduce((a, c) => a + c.speed, 0) * 1000)}s`.slice(0, 18).padEnd(20)
`${formatSize(speeds.reduce((a, c) => a + c.speed, 0))}s`.slice(0, 18).padEnd(20)
].join('')
})
9 changes: 4 additions & 5 deletions packages/cli/test/list.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ describe('list', () => {
]

it('text', async () => {
const params = mockParams({ list: items, countPeers: [{ cid, peers: 1 }], getState: [{ cid, status: 'COMPLETED', size: 50, blocks: 5 }], getSpeeds: [{ cid, speed: 1000 }] }, { group: 'group-abc' })
const params = mockParams({ list: items, countPeers: [{ cid, peers: 1 }], getState: [{ cid, status: 'COMPLETED', size: 50, blocks: 5 }] }, { group: 'group-abc' })

const response = await all(handler(params))

Expand All @@ -47,7 +47,7 @@ describe('list', () => {
[
' file ',
'50 B/500 B (10%) ',
'1000 KB/s (1 s) ',
'10 B/s (45 s) ',
'5/50 (10%) ',
'COMPLETED ',
'1 0 1 ',
Expand All @@ -65,7 +65,7 @@ describe('list', () => {
'1/1 (100%) ',
'50 B/500 B (10%) ',
'5/50 (10%) ',
'1000 KBs '
'10 Bs '
].join('')
]

Expand All @@ -76,8 +76,7 @@ describe('list', () => {
const params = mockParams({
list: items,
countPeers: [{ cid, peers: 1 }],
getState: [{ cid, status: 'COMPLETED', size: 50, blocks: 5 }],
getSpeeds: [{ cid, speed: 1000 }]
getState: [{ cid, status: 'COMPLETED', size: 50, blocks: 5 }]
}, {
group: 'group-abc',
json: true
Expand Down
12 changes: 2 additions & 10 deletions packages/client/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import {
ExportRevision,
Export,
GetSchedule,
GetSpeeds,
GetState,
ID,
Import,
Expand Down Expand Up @@ -115,15 +114,8 @@ export class Client {
return GetSchedule.Return.parse(raw)
}

async getSpeeds (cids: GetSpeeds.Params['cids'], range?: number): Promise<GetSpeeds.Return> {
const params: GetSpeeds.Params = { cids, range }
const raw = await this.client.rpc.request(GetSpeeds.name, params)

return GetSpeeds.Return.parse(raw)
}

async getState (cids: GetState.Params['cids']): Promise<GetState.Return> {
const params: GetState.Params = { cids }
async getState (cids: GetState.Params['cids'], options: Omit<GetState.Params, 'cids'> = {}): Promise<GetState.Return> {
const params: GetState.Params = { cids, ...options }
const raw = await this.client.rpc.request(GetState.name, params)

return GetState.Return.parse(raw)
Expand Down
52 changes: 0 additions & 52 deletions packages/client/test/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -471,58 +471,6 @@ describe('client', () => {
}
})

it('handles getSpeeds requests/responses', async () => {
const requests = [
{
params: {
cids: ['QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN']
},
response: [
{
cid: 'QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN',
speed: 1000000
}
]
},
{
params: {
cids: ['QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ'],
range: 1000
},
response: []
},
{
params: {
cids: [
'QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ',
'QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa'
],
range: 10000
},
response: [
{
cid: 'QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ',
speed: 0
},
{
cid: 'QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa',
speed: 1234567
}
]
}
]

for (const { params, response } of requests) {
const [req, res] = await Promise.all([
getRequest(interfaces.GetSpeeds.name, async () => response),
client.getSpeeds(params.cids, params.range)
])

assert.deepEqual(req, { ...params })
assert.deepEqual(res, response)
}
})

it('handles getStatus requests/responses', async () => {
const requests = [
{
Expand Down
21 changes: 0 additions & 21 deletions packages/daemon/src/common/commands/get-speeds.ts

This file was deleted.

2 changes: 1 addition & 1 deletion packages/daemon/src/common/commands/get-state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const command: ModuleMethod = ({ pinManager, net }) => {

const [status, { blocks, size }] = await Promise.all([
pinManager.getStatus(cid),
pinManager.getState(cid)
pinManager.getState(cid, { age: params.age })
])

return {
Expand Down
2 changes: 0 additions & 2 deletions packages/daemon/src/common/handle-commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import connect from './commands/connect.js'
import connections from './commands/connections.js'
import countPeers from './commands/count-peers.js'
import createGroup from './commands/create-group.js'
import getSpeeds from './commands/get-speeds.js'
import getState from './commands/get-state.js'
import id from './commands/id.js'
import joinGroup from './commands/join-group.js'
Expand All @@ -21,7 +20,6 @@ export default (components: Components): void => {
connections,
countPeers,
createGroup,
getSpeeds,
getState,
id,
joinGroup,
Expand Down
6 changes: 1 addition & 5 deletions packages/daemon/src/common/pin-manager/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,7 @@ export class PinManager {
return this.pinManager.getStatus(cid, options)
}

async getSpeed (cid: CID, options: { range?: number } & AbortOptions = {}): Promise<number> {
return this.pinManager.getSpeed(cid, options)
}

async getState (cid: CID, options: AbortOptions = {}): Promise<PinState> {
async getState (cid: CID, options: AbortOptions & { age?: number } = {}): Promise<PinState> {
return this.pinManager.getState(cid, options)
}

Expand Down
37 changes: 20 additions & 17 deletions packages/daemon/test/modules/downloader.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,38 +50,42 @@ describe('downloader', () => {
await components.stop()
})

it('rpc - get speed', async () => {
it('rpc - get age limited state', async () => {
const { components, socket } = await create()
const blockstore = new MemoryBlockstore()
const dag = await createDag({ blockstore }, 2, 2)
const group = 'QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN'
const path = '/test.txt'
const range = 500
const age = 500
const client = createNetClient(socket)
const key = Path.join('/', group, path)

await components.pinManager.put(key, { priority: 1, cid: dag[0] })

const speed1 = await client.rpc.request('get-speeds', {
const state1 = await client.rpc.request('get-state', {
cids: [dag[0].toString()],
range
age
})

assert.deepEqual(speed1, [{ cid: dag[0].toString(), speed: 0 }])
assert.equal(state1.length, 1)
assert.equal(state1[0].size, 0)
assert.equal(state1[0].blocks, 0)

const value = await blockstore.get(dag[0])

await components.helia.blockstore.put(dag[0], value)
await new Promise(resolve => setTimeout(resolve, range / 2))
await new Promise(resolve => setTimeout(resolve, age / 2))

const speed2 = await client.rpc.request('get-speeds', {
const state2 = await client.rpc.request('get-state', {
cids: [dag[0].toString()],
range
age
})

assert.deepEqual(speed2, [{ cid: dag[0].toString(), speed: value.length / range }])
assert.equal(state2.length, 1)
assert.equal(state2[0].size, value.length)
assert.equal(state2[0].blocks, 1)

await new Promise(resolve => setTimeout(resolve, range / 2))
await new Promise(resolve => setTimeout(resolve, age / 2))

const values = await Promise.all([
blockstore.get(dag[1]),
Expand All @@ -93,17 +97,16 @@ describe('downloader', () => {
components.helia.blockstore.put(dag[4], values[1])
])

await new Promise(resolve => setTimeout(resolve, range / 2))
await new Promise(resolve => setTimeout(resolve, age / 2))

const speed3 = await client.rpc.request('get-speeds', {
const state3 = await client.rpc.request('get-state', {
cids: [dag[0].toString()],
range
age
})

assert.deepEqual(speed3, [{
cid: dag[0].toString(),
speed: values.reduce((a, c) => c.length + a, 0) / range
}])
assert.equal(state3.length, 1)
assert.equal(state3[0].size, values.reduce((a, c) => c.length + a, 0))
assert.equal(state3[0].blocks, values.length)

client.close()
await components.stop()
Expand Down
31 changes: 3 additions & 28 deletions packages/helia-pin-manager/src/pin-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,32 +133,6 @@ export class PinManager {
return pin == null ? 'NOTFOUND' : pin.status
}

/**
* Get the download speed in bytes / millisecond.
*/
async getSpeed (cid: CID, options: { range?: number } & AbortOptions = {}): Promise<number> {
const pin = await this.pins.get(cid, options)
const range = options.range ?? 5000

if (pin == null || range <= 0) {
return 0
}

const now = Date.now()

let size = 0

for await (const block of this.blocks.all(cid, options)) {
if (block.timestamp >= now - range && block.timestamp <= now) {
size += block.size
}
}

const speed = size / range

return isNaN(speed) ? 0 : speed
}

// Get all the pins that are actively downloading.
async getActiveDownloads (options: AbortOptions = {}): Promise<CID[]> {
const cids: CID[] = []
Expand Down Expand Up @@ -194,8 +168,9 @@ export class PinManager {
/**
* Get the size on disk for a given pin.
*/
async getState (pin: CID, options: AbortOptions = {}): Promise<PinState> {
const blocks = await all(this.blocks.all(pin, options))
async getState (pin: CID, options: { age?: number } & AbortOptions = {}): Promise<PinState> {
const allBlocks = await all(this.blocks.all(pin, options))
const blocks = allBlocks.filter(b => options.age == null || b.timestamp >= Date.now() - options.age)

return {
size: blocks.reduce((c, b) => b.size + c, 0),
Expand Down
1 change: 0 additions & 1 deletion packages/rpc-interfaces/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ export * as Edit from './rpc/edit.js'
export * as ExportRevision from './rpc/export-revision.js'
export * as Export from './rpc/export.js'
export * as GetSchedule from './rpc/get-schedule.js'
export * as GetSpeeds from './rpc/get-speeds.js'
export * as GetState from './rpc/get-state.js'
export * as ID from './rpc/id.js'
export * as Import from './rpc/import.js'
Expand Down
20 changes: 0 additions & 20 deletions packages/rpc-interfaces/src/rpc/get-speeds.ts

This file was deleted.

3 changes: 2 additions & 1 deletion packages/rpc-interfaces/src/rpc/get-state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import { zCID } from '../zod.js'
export const name = 'get-state'

export const Params = z.object({
cids: z.array(zCID())
cids: z.array(zCID()),
age: z.number().optional()
})

// eslint-disable-next-line @typescript-eslint/no-redeclare
Expand Down

0 comments on commit 89c8512

Please sign in to comment.