Skip to content

Commit

Permalink
fix: adjust migration 0005 to keep delegations table but create new u…
Browse files Browse the repository at this point in the history
…sed delegations_v2 (#469)

Motivation:
* similar to #468

I think this is the one we should actually do, even though it is a
little ugly to call the table `delegations_v2`.
If d1 can't do DROP TABLE, then I think the safest thing to do is to
avoid it and always only ever create new ones. We can migrate to new
tables and update the table name access-api uses in the same commit/pr.
  • Loading branch information
gobengo committed Mar 3, 2023
1 parent 6c8242d commit a205ad1
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 78 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,11 @@ goal: remove the foreign key constraint on delegations.audience -> accounts.did.
We want to be able to store delegations whose audience is not an account did.
sqlite doesn't support `alter table drop constraint`.
So here we will:
* create delegations_new table without the constraint
* insert all from delegations -> delegations_new
* rename delegations_new -> delegations
AND cloudflare d1 doesn't support `DROP TABLE`
*/

CREATE TABLE
IF NOT EXISTS delegations_new (
IF NOT EXISTS delegations_v2 (
cid TEXT NOT NULL PRIMARY KEY,
bytes BLOB NOT NULL,
audience TEXT NOT NULL,
Expand All @@ -23,8 +20,5 @@ CREATE TABLE
UNIQUE (cid)
);

INSERT INTO delegations_new (cid, bytes, audience, issuer, expiration, inserted_at, updated_at)
INSERT INTO delegations_v2 (cid, bytes, audience, issuer, expiration, inserted_at, updated_at)
SELECT cid, bytes, audience, issuer, expiration, inserted_at, updated_at FROM delegations;

ALTER TABLE delegations RENAME TO delegations_1677808856;
ALTER TABLE delegations_new RENAME TO delegations;
52 changes: 0 additions & 52 deletions packages/access-api/src/models/accounts.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
// eslint-disable-next-line no-unused-vars
import * as Ucanto from '@ucanto/interface'
import {
delegationsToBytes,
expirationToDate,
} from '@web3-storage/access/encoding'
import { Kysely } from 'kysely'
import { D1Dialect } from 'kysely-d1'
import { GenericPlugin } from '../utils/d1.js'
Expand Down Expand Up @@ -51,26 +47,6 @@ export class Accounts {
return { data: result }
}

/**
*
* @param {Ucanto.Delegation} del
*/
async addDelegation(del) {
const result = await this.d1
.insertInto('delegations')
.values({
cid: del.cid.toV1().toString(),
audience: del.audience.did(),
issuer: del.issuer.did(),
bytes: delegationsToBytes([del]),
expires_at: expirationToDate(del.expiration),
})
.onConflict((oc) => oc.column('cid').doNothing())
.returningAll()
.executeTakeFirst()
return result
}

/**
* @param {Ucanto.URI<"did:">} did
*/
Expand All @@ -81,32 +57,4 @@ export class Accounts {
.where('accounts.did', '=', did)
.executeTakeFirst()
}

/**
* @param {Ucanto.URI<"did:">} did
*/
async getDelegations(did) {
return await this.d1
.selectFrom('delegations')
.selectAll()
.where('delegations.audience', '=', did)
.execute()
}

/**
* @param {string} cid
*/
async getDelegationsByCid(cid) {
return await this.d1
.selectFrom('delegations')
.selectAll()
.where('delegations.cid', '=', cid)
.where((qb) =>
qb
.where('delegations.expires_at', '>=', new Date())
// eslint-disable-next-line unicorn/no-null
.orWhere('delegations.expires_at', 'is', null)
)
.executeTakeFirst()
}
}
32 changes: 15 additions & 17 deletions packages/access-api/src/models/delegations.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {

/**
* @typedef Tables
* @property {DelegationRow} delegations
* @property {DelegationRow} delegations_v2
*/

/**
Expand All @@ -25,6 +25,9 @@ import {
export class DbDelegationsStorage {
/** @type {DelegationsDatabase} */
#db
#tables = {
delegations: /** @type {const} */ ('delegations_v2'),
}

/**
* @param {DelegationsDatabase} db
Expand All @@ -39,7 +42,7 @@ export class DbDelegationsStorage {

async count() {
const { size } = await this.#db
.selectFrom('delegations')
.selectFrom(this.#tables.delegations)
.select((e) => e.fn.count('cid').as('size'))
.executeTakeFirstOrThrow()
return BigInt(size)
Expand All @@ -49,7 +52,14 @@ export class DbDelegationsStorage {
* @param {import('../types/delegations').Query} query
*/
async *find(query) {
for await (const row of await selectByAudience(this.#db, query.audience)) {
const { audience } = query
const { delegations } = this.#tables
const selection = await this.#db
.selectFrom(delegations)
.selectAll()
.where(`${delegations}.audience`, '=', audience)
.execute()
for await (const row of selection) {
yield rowToDelegation(row)
}
}
Expand All @@ -66,7 +76,7 @@ export class DbDelegationsStorage {
}
const values = delegations.map((d) => createDelegationRowUpdate(d))
await this.#db
.insertInto('delegations')
.insertInto(this.#tables.delegations)
.values(values)
.onConflict((oc) => oc.column('cid').doNothing())
.executeTakeFirst()
Expand All @@ -87,7 +97,7 @@ export class DbDelegationsStorage {
)
}
for await (const row of this.#db
.selectFrom('delegations')
.selectFrom(this.#tables.delegations)
.select(['bytes'])
.stream()) {
yield rowToDelegation(row)
Expand Down Expand Up @@ -121,15 +131,3 @@ function createDelegationRowUpdate(d) {
bytes: delegationsToBytes([d]),
}
}

/**
* @param {DelegationsDatabase} db
* @param {Ucanto.DID} audience
*/
async function selectByAudience(db, audience) {
return await db
.selectFrom('delegations')
.selectAll()
.where('delegations.audience', '=', audience)
.execute()
}

0 comments on commit a205ad1

Please sign in to comment.