Skip to content

Commit

Permalink
Contract deletion handling
Browse files Browse the repository at this point in the history
  • Loading branch information
corrideat committed Jan 8, 2025
1 parent cf3e2a9 commit 0b72902
Show file tree
Hide file tree
Showing 10 changed files with 39 additions and 7 deletions.
7 changes: 3 additions & 4 deletions backend/database.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,11 @@ if (!fs.existsSync(dataFolder)) {
// Streams stored contract log entries since the given entry hash (inclusive!).
export default ((sbp('sbp/selectors/register', {
'backend/db/streamEntriesAfter': async function (contractID: string, height: string, requestedLimit: ?number): Promise<*> {
const resource = await sbp('chelonia/db/get', contractID)
if (resource === '') {
throw Boom.resourceGone(`contractID ${contractID} has been deleted!`)
}
const limit = Math.min(requestedLimit ?? Number.POSITIVE_INFINITY, process.env.MAX_EVENTS_BATCH_SIZE ?? 500)
const latestHEADinfo = await sbp('chelonia/db/latestHEADinfo', contractID)
if (latestHEADinfo === '') {
throw Boom.resourceGone(`contractID ${contractID} has been deleted!`)
}
if (!latestHEADinfo) {
throw Boom.notFound(`contractID ${contractID} doesn't exist!`)
}
Expand Down
6 changes: 5 additions & 1 deletion backend/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,11 @@ console.error = logger.error.bind(logger)

console.info('NODE_ENV =', process.env.NODE_ENV)

const dontLog = { 'backend/server/broadcastEntry': true, 'backend/server/broadcastKV': true }
const dontLog = {
'backend/server/broadcastEntry': true,
'backend/server/broadcastDeletion': true,
'backend/server/broadcastKV': true
}

function logSBP (domain, selector, data: Array<*>) {
if (!dontLog[selector]) {
Expand Down
3 changes: 3 additions & 0 deletions backend/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,9 @@ route.GET('/latestHEADinfo/{contractID}', {
try {
if (contractID.startsWith('_private')) return Boom.notFound()
const HEADinfo = await sbp('chelonia/db/latestHEADinfo', contractID)
if (HEADinfo === '') {
return Boom.resourceGone()
}
if (!HEADinfo) {
console.warn(`[backend] latestHEADinfo not found for ${contractID}`)
return Boom.notFound()
Expand Down
10 changes: 10 additions & 0 deletions backend/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,13 @@ sbp('sbp/selectors/register', {
console.debug(chalk.blue.bold(`[pubsub] Broadcasting ${deserializedHEAD.description()}`))
await pubsub.broadcast(pubsubMessage, { to: subscribers })
},
'backend/server/broadcastDeletion': async function (contractID: string) {
const pubsub = sbp('okTurtles.data/get', PUBSUB_INSTANCE)
const pubsubMessage = createMessage(NOTIFICATION_TYPE.DELETION, contractID)
const subscribers = pubsub.enumerateSubscribers(contractID)
console.debug(chalk.blue.bold(`[pubsub] Broadcasting deletion of ${contractID}`))
await pubsub.broadcast(pubsubMessage, { to: subscribers })
},
'backend/server/handleEntry': async function (deserializedHEAD: Object, entry: string) {
const contractID = deserializedHEAD.contractID
if (deserializedHEAD.head.op === GIMessage.OP_CONTRACT) {
Expand Down Expand Up @@ -306,6 +313,9 @@ sbp('sbp/selectors/register', {
await sbp('chelonia/db/delete', `_private_cheloniaState_${cid}`)
await removeFromIndexFactory('_private_cheloniaState_index')(cid)
await removeFromIndexFactory('_private_billable_entities')(cid)
sbp('backend/server/broadcastDeletion', cid).catch(e => {
console.error(e, 'Error broadcasting contract deletion', cid)
})
}).finally(() => {
contractsPendingDeletion.delete(cid)
})
Expand Down
4 changes: 3 additions & 1 deletion frontend/controller/utils/misc.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
'use strict'

import { ChelErrorUnexpectedHttpResponseCode } from '~/shared/domains/chelonia/errors.js'

export function handleFetchResult (type: string): ((r: any) => any) {
return function (r: Object) {
if (!r.ok) throw new Error(`${r.status}: ${r.statusText}`)
if (!r.ok) throw new ChelErrorUnexpectedHttpResponseCode(`${r.status}: ${r.statusText}`)
return r[type]()
}
}
10 changes: 10 additions & 0 deletions frontend/setupChelonia.js
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,12 @@ const setupChelonia = async (): Promise<*> => {
}
},
hooks: {
syncContractError: (e, contractID) => {
// TODO
if (e?.name === 'ChelErrorUnexpectedHttpResponseCode' && e.message.startsWith('410:')) {
console.error('@@@@[syncContractError] Contract ID ' + contractID + ' has been deleted')
}
},
handleEventError: (e: Error, message: GIMessage) => {
if (e.name === 'ChelErrorUnrecoverable') {
sbp('okTurtles.events/emit', SERIOUS_ERROR, e)
Expand Down Expand Up @@ -254,6 +260,10 @@ const setupChelonia = async (): Promise<*> => {
if (!data) return

sbp('okTurtles.events/emit', KV_EVENT, { contractID, key, data })
},
[NOTIFICATION_TYPE.DELETION] (contractID) {
// TODO
console.error('@@@@[NOTIFICATION] Contract ID ' + contractID + ' has been deleted')
}
},
handlers: {
Expand Down
2 changes: 2 additions & 0 deletions shared/domains/chelonia/chelonia.js
Original file line number Diff line number Diff line change
Expand Up @@ -626,6 +626,8 @@ export default (sbp('sbp/selectors/register', {
console.error(`[chelonia] Error processing kv event for ${msg.channelID} and key ${msg.key}`, msg, e)
})
}]
case NOTIFICATION_TYPE.DELETION:
return [k, (msg) => v(msg.data)]
default:
return [k, v]
}
Expand Down
2 changes: 1 addition & 1 deletion shared/domains/chelonia/db.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ export default (sbp('sbp/selectors/register', {
return sbp('chelonia/db/get', getLogHead(contractID)).then((r) => r && JSON.parse(r))
},
'chelonia/db/deleteLatestHEADinfo': (contractID: string): Promise<void> => {
return sbp('chelonia/db/delete', getLogHead(contractID))
return sbp('chelonia/db/set', getLogHead(contractID), '')
},
'chelonia/db/getEntry': async function (hash: string): Promise<GIMessage> {
try {
Expand Down
1 change: 1 addition & 0 deletions shared/domains/chelonia/errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,4 @@ export const ChelErrorSignatureError: typeof Error = ChelErrorGenerator('ChelErr
export const ChelErrorSignatureKeyUnauthorized: typeof Error = ChelErrorGenerator('ChelErrorSignatureKeyUnauthorized', ChelErrorSignatureError)
export const ChelErrorSignatureKeyNotFound: typeof Error = ChelErrorGenerator('ChelErrorSignatureKeyNotFound', ChelErrorSignatureError)
export const ChelErrorFetchServerTimeFailed: typeof Error = ChelErrorGenerator('ChelErrorFetchServerTimeFailed')
export const ChelErrorUnexpectedHttpResponseCode: typeof Error = ChelErrorGenerator('ChelErrorUnexpectedHttpResponseCode')
1 change: 1 addition & 0 deletions shared/pubsub.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ export type UnsubMessage = {

export const NOTIFICATION_TYPE = Object.freeze({
ENTRY: 'entry',
DELETION: 'deletion',
KV: 'kv',
PING: 'ping',
PONG: 'pong',
Expand Down

0 comments on commit 0b72902

Please sign in to comment.