184 lines
4.9 KiB
TypeScript
184 lines
4.9 KiB
TypeScript
import {
|
|
Event,
|
|
BackfillMetadata,
|
|
CachedEvent,
|
|
SSOCreatedEvent,
|
|
AutomationCreatedEvent,
|
|
AutomationStepCreatedEvent,
|
|
DatasourceCreatedEvent,
|
|
LayoutCreatedEvent,
|
|
QueryCreatedEvent,
|
|
RoleCreatedEvent,
|
|
ScreenCreatedEvent,
|
|
TableCreatedEvent,
|
|
ViewCreatedEvent,
|
|
ViewCalculationCreatedEvent,
|
|
ViewFilterCreatedEvent,
|
|
AppPublishedEvent,
|
|
UserCreatedEvent,
|
|
RoleAssignedEvent,
|
|
UserPermissionAssignedEvent,
|
|
AppCreatedEvent,
|
|
} from "@budibase/types"
|
|
import * as context from "../context"
|
|
import { CacheKeys } from "../cache/generic"
|
|
import * as cache from "../cache/generic"
|
|
|
|
// LIFECYCLE
|
|
|
|
export const start = async (events: Event[]) => {
|
|
const metadata: BackfillMetadata = {
|
|
eventWhitelist: events,
|
|
}
|
|
return saveBackfillMetadata(metadata)
|
|
}
|
|
|
|
export const recordEvent = async (event: Event, properties: any) => {
|
|
const eventKey = getEventKey(event, properties)
|
|
// don't use a ttl - cleaned up by migration
|
|
// don't use tenancy - already in the key
|
|
await cache.store(eventKey, properties, undefined, { useTenancy: false })
|
|
}
|
|
|
|
export const end = async () => {
|
|
await deleteBackfillMetadata()
|
|
await clearEvents()
|
|
}
|
|
|
|
// CRUD
|
|
|
|
const getBackfillMetadata = async (): Promise<BackfillMetadata | null> => {
|
|
return cache.get(CacheKeys.BACKFILL_METADATA)
|
|
}
|
|
|
|
const saveBackfillMetadata = async (
|
|
backfill: BackfillMetadata
|
|
): Promise<void> => {
|
|
// no TTL - deleted by backfill
|
|
return cache.store(CacheKeys.BACKFILL_METADATA, backfill)
|
|
}
|
|
|
|
const deleteBackfillMetadata = async (): Promise<void> => {
|
|
await cache.delete(CacheKeys.BACKFILL_METADATA)
|
|
}
|
|
|
|
const clearEvents = async () => {
|
|
// wildcard
|
|
const pattern = getEventKey()
|
|
const keys = await cache.keys(pattern)
|
|
|
|
for (const key of keys) {
|
|
// delete each key
|
|
// don't use tenancy, already in the key
|
|
await cache.delete(key, { useTenancy: false })
|
|
}
|
|
}
|
|
|
|
// HELPERS
|
|
|
|
export const isBackfillingEvent = async (event: Event) => {
|
|
const backfill = await getBackfillMetadata()
|
|
const events = backfill?.eventWhitelist
|
|
if (events && events.includes(event)) {
|
|
return true
|
|
} else {
|
|
return false
|
|
}
|
|
}
|
|
|
|
export const isAlreadySent = async (event: Event, properties: any) => {
|
|
const eventKey = getEventKey(event, properties)
|
|
const cachedEvent: CachedEvent = await cache.get(eventKey, {
|
|
useTenancy: false,
|
|
})
|
|
return !!cachedEvent
|
|
}
|
|
|
|
const CUSTOM_PROPERTY_SUFFIX: any = {
|
|
// APP EVENTS
|
|
[Event.AUTOMATION_CREATED]: (properties: AutomationCreatedEvent) => {
|
|
return properties.automationId
|
|
},
|
|
[Event.AUTOMATION_STEP_CREATED]: (properties: AutomationStepCreatedEvent) => {
|
|
return properties.stepId
|
|
},
|
|
[Event.DATASOURCE_CREATED]: (properties: DatasourceCreatedEvent) => {
|
|
return properties.datasourceId
|
|
},
|
|
[Event.LAYOUT_CREATED]: (properties: LayoutCreatedEvent) => {
|
|
return properties.layoutId
|
|
},
|
|
[Event.QUERY_CREATED]: (properties: QueryCreatedEvent) => {
|
|
return properties.queryId
|
|
},
|
|
[Event.ROLE_CREATED]: (properties: RoleCreatedEvent) => {
|
|
return properties.roleId
|
|
},
|
|
[Event.SCREEN_CREATED]: (properties: ScreenCreatedEvent) => {
|
|
return properties.screenId
|
|
},
|
|
[Event.TABLE_CREATED]: (properties: TableCreatedEvent) => {
|
|
return properties.tableId
|
|
},
|
|
[Event.VIEW_CREATED]: (properties: ViewCreatedEvent) => {
|
|
return properties.tableId // best uniqueness
|
|
},
|
|
[Event.VIEW_CALCULATION_CREATED]: (
|
|
properties: ViewCalculationCreatedEvent
|
|
) => {
|
|
return properties.tableId // best uniqueness
|
|
},
|
|
[Event.VIEW_FILTER_CREATED]: (properties: ViewFilterCreatedEvent) => {
|
|
return properties.tableId // best uniqueness
|
|
},
|
|
[Event.APP_CREATED]: (properties: AppCreatedEvent) => {
|
|
return properties.appId // best uniqueness
|
|
},
|
|
[Event.APP_PUBLISHED]: (properties: AppPublishedEvent) => {
|
|
return properties.appId // best uniqueness
|
|
},
|
|
// GLOBAL EVENTS
|
|
[Event.AUTH_SSO_CREATED]: (properties: SSOCreatedEvent) => {
|
|
return properties.type
|
|
},
|
|
[Event.AUTH_SSO_ACTIVATED]: (properties: SSOCreatedEvent) => {
|
|
return properties.type
|
|
},
|
|
[Event.USER_CREATED]: (properties: UserCreatedEvent) => {
|
|
return properties.userId
|
|
},
|
|
[Event.USER_PERMISSION_ADMIN_ASSIGNED]: (
|
|
properties: UserPermissionAssignedEvent
|
|
) => {
|
|
return properties.userId
|
|
},
|
|
[Event.USER_PERMISSION_BUILDER_ASSIGNED]: (
|
|
properties: UserPermissionAssignedEvent
|
|
) => {
|
|
return properties.userId
|
|
},
|
|
[Event.ROLE_ASSIGNED]: (properties: RoleAssignedEvent) => {
|
|
return `${properties.roleId}-${properties.userId}`
|
|
},
|
|
}
|
|
|
|
const getEventKey = (event?: Event, properties?: any) => {
|
|
let eventKey: string
|
|
|
|
const tenantId = context.getTenantId()
|
|
if (event) {
|
|
eventKey = `${CacheKeys.EVENTS}:${tenantId}:${event}`
|
|
|
|
// use some properties to make the key more unique
|
|
const custom = CUSTOM_PROPERTY_SUFFIX[event]
|
|
const suffix = custom ? custom(properties) : undefined
|
|
if (suffix) {
|
|
eventKey = `${eventKey}:${suffix}`
|
|
}
|
|
} else {
|
|
eventKey = `${CacheKeys.EVENTS}:${tenantId}:*`
|
|
}
|
|
|
|
return eventKey
|
|
}
|