Better handle first time startup + dedicated event

This commit is contained in:
Rory Powell 2022-06-15 11:20:13 +01:00
parent 92d5039dfb
commit 4cfedf7252
10 changed files with 57 additions and 29 deletions

View File

@ -7,7 +7,10 @@ import PosthogProcessor from "./PosthogProcessor"
/** /**
* Events that are always captured. * Events that are always captured.
*/ */
const EVENT_WHITELIST = [Event.VERSION_UPGRADED, Event.VERSION_DOWNGRADED] const EVENT_WHITELIST = [
Event.INSTALLATION_VERSION_UPGRADED,
Event.INSTALLATION_VERSION_DOWNGRADED,
]
const IDENTITY_WHITELIST = [IdentityType.INSTALLATION, IdentityType.TENANT] const IDENTITY_WHITELIST = [IdentityType.INSTALLATION, IdentityType.TENANT]
export default class AnalyticsProcessor implements EventProcessor { export default class AnalyticsProcessor implements EventProcessor {

View File

@ -15,5 +15,5 @@ export * as table from "./table"
export * as serve from "./serve" export * as serve from "./serve"
export * as user from "./user" export * as user from "./user"
export * as view from "./view" export * as view from "./view"
export * as version from "./version" export * as installation from "./installation"
export * as backfill from "./backfill" export * as backfill from "./backfill"

View File

@ -1,11 +1,11 @@
import { publishEvent } from "../events" import { publishEvent } from "../events"
import { Event, VersionCheckedEvent, VersionChangeEvent } from "@budibase/types" import { Event, VersionCheckedEvent, VersionChangeEvent } from "@budibase/types"
export async function checked(version: string) { export async function versionChecked(version: string) {
const properties: VersionCheckedEvent = { const properties: VersionCheckedEvent = {
currentVersion: version, currentVersion: version,
} }
await publishEvent(Event.VERSION_CHECKED, properties) await publishEvent(Event.INSTALLATION_VERSION_CHECKED, properties)
} }
export async function upgraded(from: string, to: string) { export async function upgraded(from: string, to: string) {
@ -14,7 +14,7 @@ export async function upgraded(from: string, to: string) {
to, to,
} }
await publishEvent(Event.VERSION_UPGRADED, properties) await publishEvent(Event.INSTALLATION_VERSION_UPGRADED, properties)
} }
export async function downgraded(from: string, to: string) { export async function downgraded(from: string, to: string) {
@ -22,5 +22,10 @@ export async function downgraded(from: string, to: string) {
from, from,
to, to,
} }
await publishEvent(Event.VERSION_DOWNGRADED, properties) await publishEvent(Event.INSTALLATION_VERSION_DOWNGRADED, properties)
}
export async function firstStartup() {
const properties = {}
await publishEvent(Event.INSTALLATION_FIRST_STARTUP, properties)
} }

View File

@ -84,9 +84,9 @@ export const checkInstallVersion = async (): Promise<void> => {
}, },
async () => { async () => {
if (isUpgrade) { if (isUpgrade) {
await events.version.upgraded(currentVersion, newVersion) await events.installation.upgraded(currentVersion, newVersion)
} else if (isDowngrade) { } else if (isDowngrade) {
await events.version.downgraded(currentVersion, newVersion) await events.installation.downgraded(currentVersion, newVersion)
} }
} }
) )

View File

@ -55,7 +55,7 @@ jest.spyOn(events.org, "logoUpdated")
jest.spyOn(events.org, "platformURLUpdated") jest.spyOn(events.org, "platformURLUpdated")
jest.spyOn(events.org, "analyticsOptOut") jest.spyOn(events.org, "analyticsOptOut")
jest.spyOn(events.version, "checked") jest.spyOn(events.installation, "versionChecked")
jest.spyOn(events.query, "created") jest.spyOn(events.query, "created")
jest.spyOn(events.query, "updated") jest.spyOn(events.query, "updated")

View File

@ -131,5 +131,5 @@ exports.getBudibaseVersion = async ctx => {
ctx.body = { ctx.body = {
version, version,
} }
await events.version.checked(version) await events.installation.versionChecked(version)
} }

View File

@ -33,8 +33,8 @@ describe("/dev", () => {
.expect(200) .expect(200)
expect(res.body.version).toBe(version) expect(res.body.version).toBe(version)
expect(events.version.checked).toBeCalledTimes(1) expect(events.installation.versionChecked).toBeCalledTimes(1)
expect(events.version.checked).toBeCalledWith(version) expect(events.installation.versionChecked).toBeCalledWith(version)
}) })
}) })
}) })

View File

@ -14,6 +14,7 @@ import {
App, App,
TenantBackfillSucceededEvent, TenantBackfillSucceededEvent,
Event, Event,
User,
} from "@budibase/types" } from "@budibase/types"
import env from "../../../environment" import env from "../../../environment"
import { DEFAULT_TIMESTAMP } from "." import { DEFAULT_TIMESTAMP } from "."
@ -94,8 +95,22 @@ export const run = async (db: any) => {
const totals: any = {} const totals: any = {}
const errors: any = [] const errors: any = []
let allUsers: User[] = []
try { try {
const installTimestamp = await getInstallTimestamp(db) allUsers = await users.getUsers(db)
} catch (e: any) {
handleError(e, errors)
}
if (!allUsers || allUsers.length === 0) {
// first time startup - we don't need to backfill anything
// tenant will be identified when admin user is created
await events.installation.firstStartup()
return
}
try {
const installTimestamp = await getInstallTimestamp(db, allUsers)
if (installTimestamp) { if (installTimestamp) {
timestamp = installTimestamp timestamp = installTimestamp
} }
@ -175,20 +190,25 @@ export const isComplete = async (): Promise<boolean> => {
} }
export const getInstallTimestamp = async ( export const getInstallTimestamp = async (
globalDb: any globalDb: any,
allUsers?: User[]
): Promise<number | undefined> => { ): Promise<number | undefined> => {
const allUsers = await users.getUsers(globalDb) if (!allUsers) {
allUsers = await users.getUsers(globalDb)
}
// get the oldest user timestamp // get the oldest user timestamp
const timestamps = allUsers if (allUsers) {
.map(user => user.createdAt) const timestamps = allUsers
.filter(timestamp => !!timestamp) .map(user => user.createdAt)
.sort( .filter(timestamp => !!timestamp)
(a, b) => .sort(
new Date(a as number).getTime() - new Date(b as number).getTime() (a, b) =>
) new Date(a as number).getTime() - new Date(b as number).getTime()
)
if (timestamps.length) { if (timestamps.length) {
return timestamps[0] return timestamps[0]
}
} }
} }

View File

@ -104,7 +104,6 @@ export const migrate = async (options?: MigrationOptions) => {
const migrateWithLock = async (options?: MigrationOptions) => { const migrateWithLock = async (options?: MigrationOptions) => {
// get a new lock client // get a new lock client
const redlock = await redis.clients.getMigrationsRedlock() const redlock = await redis.clients.getMigrationsRedlock()
// lock for 15 minutes // lock for 15 minutes
const ttl = 1000 * 60 * 15 const ttl = 1000 * 60 * 15

View File

@ -39,10 +39,11 @@ export enum Event {
ORG_LOGO_UPDATED = "org:info:logo:updated", ORG_LOGO_UPDATED = "org:info:logo:updated",
ORG_PLATFORM_URL_UPDATED = "org:platformurl:updated", ORG_PLATFORM_URL_UPDATED = "org:platformurl:updated",
// VERSIONS // INSTALLATION
VERSION_CHECKED = "version:checked", INSTALLATION_VERSION_CHECKED = "installation:version:checked",
VERSION_UPGRADED = "version:upgraded", INSTALLATION_VERSION_UPGRADED = "installation:version:upgraded",
VERSION_DOWNGRADED = "version:downgraded", INSTALLATION_VERSION_DOWNGRADED = "installation:version:downgraded",
INSTALLATION_FIRST_STARTUP = "installation:firstStartup",
// ORG / ANALYTICS // ORG / ANALYTICS
ANALYTICS_OPT_OUT = "analytics:opt:out", ANALYTICS_OPT_OUT = "analytics:opt:out",