From 70020d4354ca807e906e067c39395756ba9c99f4 Mon Sep 17 00:00:00 2001 From: wa0x6e <495709+wa0x6e@users.noreply.github.com> Date: Wed, 28 May 2025 11:43:24 +0400 Subject: [PATCH] fix: remove `turbo` column --- src/graphql/helpers.ts | 8 +---- src/graphql/operations/follows.ts | 1 - src/graphql/operations/proposal.ts | 1 - src/graphql/operations/proposals.ts | 1 - src/graphql/operations/subscriptions.ts | 1 - src/graphql/operations/votes.ts | 1 - src/helpers/metrics.ts | 30 ++++++++++------ src/helpers/schema.sql | 2 -- src/helpers/spaces.ts | 14 ++++---- test/e2e/space.test.ts | 47 +++++++++++++++---------- test/fixtures/spaces.ts | 2 -- 11 files changed, 56 insertions(+), 52 deletions(-) diff --git a/src/graphql/helpers.ts b/src/graphql/helpers.ts index c1be16b0..d2f1157e 100644 --- a/src/graphql/helpers.ts +++ b/src/graphql/helpers.ts @@ -87,7 +87,6 @@ export function formatSpace({ settings, domain, verified, - turbo, turboExpiration, flagged, hibernated, @@ -143,8 +142,7 @@ export function formatSpace({ space.verified = verified ?? null; space.flagged = flagged ?? null; space.hibernated = hibernated ?? null; - space.turbo = - new Date((turboExpiration || 0) * 1000) > new Date() ? true : turbo ?? null; + space.turbo = new Date((turboExpiration || 0) * 1000) > new Date(); space.turboExpiration = turboExpiration ?? 0; space.rank = spaceMetadata?.rank ?? null; @@ -449,7 +447,6 @@ export function formatProposal(proposal) { settings: proposal.settings, domain: proposal.spaceDomain, verified: proposal.spaceVerified, - turbo: proposal.spaceTurbo, turboExpiration: proposal.spaceTurboExpiration, flagged: proposal.spaceFlagged, hibernated: proposal.spaceHibernated, @@ -476,7 +473,6 @@ export function formatVote(vote) { domain: vote.spaceDomain, settings: vote.settings, verified: vote.spaceVerified, - turbo: vote.spaceTurbo, turboExpiration: vote.spaceTurboExpiration, flagged: vote.spaceFlagged, hibernated: vote.spaceHibernated, @@ -491,7 +487,6 @@ export function formatFollow(follow) { settings: follow.settings, domain: follow.spaceDomain, verified: follow.spaceVerified, - turbo: follow.spaceTurbo, turboExpiration: follow.spaceTurboExpiration, flagged: follow.spaceFlagged, hibernated: follow.spaceHibernated, @@ -506,7 +501,6 @@ export function formatSubscription(subscription) { settings: subscription.settings, domain: subscription.spaceDomain, verified: subscription.spaceVerified, - turbo: subscription.spaceTurbo, turboExpiration: subscription.spaceTurboExpiration, flagged: subscription.spaceFlagged, hibernated: subscription.spaceHibernated, diff --git a/src/graphql/operations/follows.ts b/src/graphql/operations/follows.ts index 262bcaa0..638c7b9a 100644 --- a/src/graphql/operations/follows.ts +++ b/src/graphql/operations/follows.ts @@ -36,7 +36,6 @@ export default async function (parent, args) { spaces.domain as spaceDomain, spaces.flagged as spaceFlagged, spaces.verified as spaceVerified, - spaces.turbo as spaceTurbo, spaces.turbo_expiration as spaceTurboExpiration, spaces.hibernated as spaceHibernated FROM follows f diff --git a/src/graphql/operations/proposal.ts b/src/graphql/operations/proposal.ts index a54538d5..e5766401 100644 --- a/src/graphql/operations/proposal.ts +++ b/src/graphql/operations/proposal.ts @@ -13,7 +13,6 @@ export default async function (parent, { id }) { spaces.domain as spaceDomain, spaces.flagged as spaceFlagged, spaces.verified as spaceVerified, - spaces.turbo as spaceTurbo, spaces.turbo_expiration as spaceTurboExpiration, spaces.hibernated as spaceHibernated FROM proposals p diff --git a/src/graphql/operations/proposals.ts b/src/graphql/operations/proposals.ts index 9e31ebf3..cc8e1ba7 100644 --- a/src/graphql/operations/proposals.ts +++ b/src/graphql/operations/proposals.ts @@ -95,7 +95,6 @@ export default async function (parent, args) { spaces.domain as spaceDomain, spaces.flagged as spaceFlagged, spaces.verified as spaceVerified, - spaces.turbo as spaceTurbo, spaces.turbo_expiration as spaceTurboExpiration, spaces.hibernated as spaceHibernated FROM proposals p diff --git a/src/graphql/operations/subscriptions.ts b/src/graphql/operations/subscriptions.ts index 6f5e1d2a..c89f9808 100644 --- a/src/graphql/operations/subscriptions.ts +++ b/src/graphql/operations/subscriptions.ts @@ -37,7 +37,6 @@ export default async function (parent, args) { spaces.domain as spaceDomain, spaces.flagged as spaceFlagged, spaces.verified as spaceVerified, - spaces.turbo as spaceTurbo, spaces.turbo_expiration as spaceTurboExpiration, spaces.hibernated as spaceHibernated FROM subscriptions s diff --git a/src/graphql/operations/votes.ts b/src/graphql/operations/votes.ts index 5f1b55bf..21f34a48 100644 --- a/src/graphql/operations/votes.ts +++ b/src/graphql/operations/votes.ts @@ -101,7 +101,6 @@ async function query(parent, args, context?, info?) { spaces.domain as spaceDomain, spaces.flagged as spaceFlagged, spaces.verified as spaceVerified, - spaces.turbo as spaceTurbo, spaces.turbo_expiration as spaceTurboExpiration, spaces.hibernated as spaceHibernated FROM proposals p diff --git a/src/helpers/metrics.ts b/src/helpers/metrics.ts index b538fc6d..04289de4 100644 --- a/src/helpers/metrics.ts +++ b/src/helpers/metrics.ts @@ -95,16 +95,26 @@ new client.Gauge({ help: 'Number of spaces per status', labelNames: ['status'], async collect() { - ['verified', 'flagged', 'turbo', 'hibernated'].forEach(async status => { - this.set( - { status }, - ( - await db.queryAsync( - `SELECT COUNT(id) as count FROM spaces WHERE ${status} = 1` - ) - )[0].count - ); - }); + const statusQueries = [ + { status: 'verified', column: 'verified', pivot: 0 }, + { status: 'flagged', column: 'flagged', pivot: 0 }, + { + status: 'turbo', + column: 'turbo_expiration', + pivot: Math.floor(Date.now() / 1000) + }, + { status: 'hibernated', column: 'hibernated', pivot: 0 } + ]; + + await Promise.all( + statusQueries.map(async ({ status, column, pivot }) => { + const [{ count }] = await db.queryAsync( + `SELECT COUNT(id) as count FROM spaces WHERE ${column} > ?`, + [pivot] + ); + this.set({ status }, count); + }) + ); } }); diff --git a/src/helpers/schema.sql b/src/helpers/schema.sql index 230e2eb2..9e4032f6 100644 --- a/src/helpers/schema.sql +++ b/src/helpers/schema.sql @@ -6,7 +6,6 @@ CREATE TABLE spaces ( deleted INT NOT NULL DEFAULT '0', flagged INT NOT NULL DEFAULT '0', hibernated INT NOT NULL DEFAULT '0', - turbo INT NOT NULL DEFAULT '0', turbo_expiration BIGINT NOT NULL DEFAULT '0', proposal_count INT NOT NULL DEFAULT '0', vote_count INT NOT NULL DEFAULT '0', @@ -20,7 +19,6 @@ CREATE TABLE spaces ( INDEX verified (verified), INDEX flagged (flagged), INDEX hibernated (hibernated), - INDEX turbo (turbo), INDEX proposal_count (proposal_count), INDEX vote_count (vote_count), INDEX follower_count (follower_count), diff --git a/src/helpers/spaces.ts b/src/helpers/spaces.ts index 633a8493..dce6bdc2 100644 --- a/src/helpers/spaces.ts +++ b/src/helpers/spaces.ts @@ -56,8 +56,8 @@ type Metadata = { pluginNames: string[]; }; -function isTurbo(turbo: boolean, turboExpiration: number): boolean { - return turbo || turboExpiration > Date.now() / 1e3; +function isTurbo(turboExpiration: number): boolean { + return turboExpiration > Date.now() / 1e3; } function getPopularity(space: Metadata): number { @@ -128,7 +128,7 @@ function mapSpaces(spaces: Record) { name: space.name, verified: space.verified, flagged: space.flagged, - turbo: isTurbo(space.turbo, space.turboExpiration), + turbo: isTurbo(space.turboExpiration), turboExpiration: space.turboExpiration, hibernated: space.hibernated, parent: space.parent, @@ -160,7 +160,7 @@ async function loadSpaces() { const startTime = +Date.now(); const query = ` - SELECT id, settings, flagged, verified, turbo, turbo_expiration, hibernated, follower_count, proposal_count, vote_count + SELECT id, settings, flagged, verified, turbo_expiration, hibernated, follower_count, proposal_count, vote_count FROM spaces WHERE deleted = 0 ORDER BY id ASC @@ -174,7 +174,7 @@ async function loadSpaces() { ...JSON.parse(space.settings), flagged: space.flagged === 1, verified: space.verified === 1, - turbo: isTurbo(!!space.turbo, space.turbo_expiration), + turbo: isTurbo(space.turbo_expiration), turboExpiration: space.turbo_expiration, hibernated: space.hibernated === 1, follower_count: space.follower_count, @@ -307,7 +307,7 @@ async function loadSpacesMetrics() { export async function getSpace(id: string) { const query = ` - SELECT settings, domain, flagged, verified, turbo, turbo_expiration, hibernated, deleted, follower_count, proposal_count, vote_count + SELECT settings, domain, flagged, verified, turbo_expiration, hibernated, deleted, follower_count, proposal_count, vote_count FROM spaces WHERE id = ? LIMIT 1`; @@ -321,7 +321,7 @@ export async function getSpace(id: string) { domain: space.domain, flagged: space.flagged === 1, verified: space.verified === 1, - turbo: isTurbo(!!space.turbo, space.turbo_expiration), + turbo: isTurbo(space.turbo_expiration), turboExpiration: space.turbo_expiration, hibernated: space.hibernated === 1, deleted: space.deleted === 1 diff --git a/test/e2e/space.test.ts b/test/e2e/space.test.ts index 7e5b6c2b..ce7cbfc4 100644 --- a/test/e2e/space.test.ts +++ b/test/e2e/space.test.ts @@ -23,12 +23,9 @@ describe('GET /api/space/:key', () => { }); describe('when the space exists', () => { - let response; - beforeAll(async () => { - response = await fetch(`${HOST}/api/spaces/${fixtures[0].id}`); - }); + it('returns the correct HTTP response', async () => { + const response = await fetch(`${HOST}/api/spaces/${fixtures[0].id}`); - it('returns the correct HTTP response', () => { expect(response.status); expect(response.headers.get('content-type')).toContain( 'application/json' @@ -37,10 +34,12 @@ describe('GET /api/space/:key', () => { it('returns the space data', async () => { const space = fixtures[0]; + const response = await fetch(`${HOST}/api/spaces/${space.id}`); + const expectedSpace = { flagged: space.flagged, verified: space.verified, - turbo: space.turbo, + turbo: false, turboExpiration: space.turbo_expiration, hibernated: space.hibernated, deleted: false, @@ -48,7 +47,7 @@ describe('GET /api/space/:key', () => { ...space.settings }; - expect(response.json()).resolves.toEqual(expectedSpace); + expect(await response.json()).toEqual(expectedSpace); }); }); @@ -60,7 +59,7 @@ describe('GET /api/space/:key', () => { expect(response.headers.get('content-type')).toContain( 'application/json' ); - expect(response.json()).resolves.toEqual({ + expect(await response.json()).toEqual({ error: 'unauthorized', error_description: 'not_found' }); @@ -71,19 +70,29 @@ describe('GET /api/space/:key', () => { it('returns the space data with a deleted:true', async () => { const response = await fetch(`${HOST}/api/spaces/${fixtures[1].id}`); - const space = fixtures[1]; - const expectedSpace = { - flagged: space.flagged, - verified: space.verified, - turbo: space.turbo, - turboExpiration: space.turbo_expiration, - hibernated: space.hibernated, - deleted: true, - domain: space.domain, - ...space.settings + expect(await response.json()).toEqual( + expect.objectContaining({ deleted: true }) + ); + }); + }); + + describe('when the space is turbo', () => { + it('returns the space as turbo', async () => { + const turboExpiration = Math.floor(Date.now() / 1e3) + 86400; // 1 day from now + const turboSpace = { + ...fixtures[0], + id: 'turbo-space.eth', + turbo_expiration: turboExpiration, + settings: JSON.stringify(fixtures[0].settings), + domain: 'turbo.com' }; + await db.queryAsync('INSERT INTO spaces SET ?', turboSpace); + + const response = await fetch(`${HOST}/api/spaces/${turboSpace.id}`); - expect(response.json()).resolves.toEqual(expectedSpace); + expect(await response.json()).toEqual( + expect.objectContaining({ turbo: true, turboExpiration }) + ); }); }); }); diff --git a/test/fixtures/spaces.ts b/test/fixtures/spaces.ts index 2f98340c..041c8179 100644 --- a/test/fixtures/spaces.ts +++ b/test/fixtures/spaces.ts @@ -4,7 +4,6 @@ const fixtures: Record[] = [ name: 'Fabien.eth', flagged: false, verified: true, - turbo: false, turbo_expiration: 0, hibernated: false, domain: 'test.com', @@ -17,7 +16,6 @@ const fixtures: Record[] = [ name: 'snap.eth', flagged: false, verified: true, - turbo: false, turbo_expiration: 0, hibernated: false, deleted: true,