Skip to content
This repository was archived by the owner on Nov 4, 2021. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 6 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,6 @@ There's a multitude of settings you can use to control the plugin server. Use th
| KAFKA_PRODUCER_MAX_QUEUE_SIZE | Kafka producer batch max size before flushing | `20` |
| KAFKA_FLUSH_FREQUENCY_MS | Kafka producer batch max duration before flushing | `500` |
| KAFKA_MAX_MESSAGE_BATCH_SIZE | Kafka producer batch max size in bytes before flushing | `900000` |
| DISABLE_WEB | whether to disable web server | `true` |
| WEB_PORT | port for web server to listen on | `3008` |
| WEB_HOSTNAME | hostname for web server to listen on | `'0.0.0.0'` |
| LOG_LEVEL | minimum log level | `LogLevel.Info` |
| SENTRY_DSN | Sentry ingestion URL | `null` |
| STATSD_HOST | StatsD host - integration disabled if this is not provided | `null` |
Expand Down Expand Up @@ -87,26 +84,24 @@ Let's talk about the main thread first. This has:

1. `pubSub` – Redis powered pub-sub mechanism for reloading plugins whenever a message is published by the main PostHog app.

2. `hub` – Handler of connections to required DBs and queues (ClickHouse, Kafka, Postgres, Redis), holds loaded plugins.
1. `hub` – Handler of connections to required DBs and queues (ClickHouse, Kafka, Postgres, Redis), holds loaded plugins.
Created via `hub.ts -> createHub`. Every thread has its own instance.

3. `fastifyInstance` – Web server. Unused for now.
1. `piscina` – Manager of tasks delegated to threads. `makePiscina` creates the manager, while `createWorker` creates the worker threads.

4. `piscina` – Manager of tasks delegated to threads. `makePiscina` creates the manager, while `createWorker` creates the worker threads.

5. `scheduleControl` – Controller of scheduled jobs. Responsible for adding Piscina tasks for scheduled jobs, when the time comes. The schedule information makes it into the controller when plugin VMs are created.
1. `scheduleControl` – Controller of scheduled jobs. Responsible for adding Piscina tasks for scheduled jobs, when the time comes. The schedule information makes it into the controller when plugin VMs are created.

Scheduled tasks are controlled with [Redlock](https://redis.io/topics/distlock) (redis-based distributed lock), and run on only one plugin server instance in the entire cluster.

6. `jobQueueConsumer` – The internal job queue consumer. This enables retries, scheduling jobs in the future (once) (Note: this is the difference between `scheduleControl` and this internal `jobQueue`). While `scheduleControl` is triggered via `runEveryMinute`, `runEveryHour` tasks, the `jobQueueConsumer` deals with `meta.jobs.doX(event).runAt(new Date())`.
1. `jobQueueConsumer` – The internal job queue consumer. This enables retries, scheduling jobs in the future (once) (Note: this is the difference between `scheduleControl` and this internal `jobQueue`). While `scheduleControl` is triggered via `runEveryMinute`, `runEveryHour` tasks, the `jobQueueConsumer` deals with `meta.jobs.doX(event).runAt(new Date())`.

Jobs are enqueued by `job-queue-manager.ts`, which is backed by Postgres-based [Graphile-worker](https://github.com/graphile/worker) (`graphile-queue.ts`).

7. `queue` – Event ingestion queue. This is a Celery (backed by Redis) or Kafka queue, depending on the setup (EE/Cloud is Kafka due to high volume). These are consumed by the `queue` above, and sent off to the Piscina workers (`src/main/ingestion-queues/queue.ts -> ingestEvent`). Since all of the actual ingestion happens inside worker threads, you'll find the specific ingestion code there (`src/worker/ingestion/ingest-event.ts`). There the data is saved into Postgres (and ClickHouse via Kafka on EE/Cloud).
1. `queue` – Event ingestion queue. This is a Celery (backed by Redis) or Kafka queue, depending on the setup (EE/Cloud is Kafka due to high volume). These are consumed by the `queue` above, and sent off to the Piscina workers (`src/main/ingestion-queues/queue.ts -> ingestEvent`). Since all of the actual ingestion happens inside worker threads, you'll find the specific ingestion code there (`src/worker/ingestion/ingest-event.ts`). There the data is saved into Postgres (and ClickHouse via Kafka on EE/Cloud).

It's also a good idea to see the producer side of this ingestion queue, which comes from `Posthog/posthog/api/capture.py`. The plugin server gets the `process_event_with_plugins` Celery task from there, in the Postgres pipeline. The ClickHouse via Kafka pipeline gets the data by way of Kafka topic `events_plugin_ingestion`.

8. `mmdbServer` – TCP server, which works as an interface between the GeoIP MMDB data reader located in main thread memory and plugins ran in worker threads of the same plugin server instance. This way the GeoIP reader is only loaded in one thread and can be used in all. Additionally this mechanism ensures that `mmdbServer` is ready before ingestion is started (database downloaded from [http-mmdb](https://github.com/PostHog/http-mmdb) and read), and keeps the database up to date in the background.
1. `mmdbServer` – TCP server, which works as an interface between the GeoIP MMDB data reader located in main thread memory and plugins ran in worker threads of the same plugin server instance. This way the GeoIP reader is only loaded in one thread and can be used in all. Additionally this mechanism ensures that `mmdbServer` is ready before ingestion is started (database downloaded from [http-mmdb](https://github.com/PostHog/http-mmdb) and read), and keeps the database up to date in the background.

### Worker threads

Expand Down
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@
"adm-zip": "^0.4.16",
"aws-sdk": "^2.884.0",
"fast-deep-equal": "^3.1.3",
"fastify": "^3.8.0",
"generic-pool": "^3.7.1",
"graphile-worker": "^0.11.1",
"hot-shots": "^8.2.1",
Expand Down
6 changes: 0 additions & 6 deletions src/config/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,6 @@ export function getDefaultConfig(): PluginsServerConfig {
POSTHOG_REDIS_PORT: 6379,
BASE_DIR: '.',
PLUGINS_RELOAD_PUBSUB_CHANNEL: 'reload-plugins',
DISABLE_WEB: true,
WEB_PORT: 3008,
WEB_HOSTNAME: '0.0.0.0',
WORKER_CONCURRENCY: coreCount,
TASK_TIMEOUT: 30,
TASKS_PER_WORKER: 10,
Expand Down Expand Up @@ -88,9 +85,6 @@ export function getConfigHelp(): Record<keyof PluginsServerConfig, string> {
REDIS_URL: 'Redis store URL',
BASE_DIR: 'base path for resolving local plugins',
PLUGINS_RELOAD_PUBSUB_CHANNEL: 'Redis channel for reload events',
DISABLE_WEB: 'whether to disable web server',
WEB_PORT: 'port for web server to listen on',
WEB_HOSTNAME: 'hostname for web server to listen on',
WORKER_CONCURRENCY: 'number of concurrent worker threads',
TASK_TIMEOUT: 'how many seconds until tasks are timed out',
TASKS_PER_WORKER: 'number of parallel tasks per worker thread',
Expand Down
9 changes: 0 additions & 9 deletions src/main/pluginsServer.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { ReaderModel } from '@maxmind/geoip2-node'
import Piscina from '@posthog/piscina'
import * as Sentry from '@sentry/node'
import { FastifyInstance } from 'fastify'
import net, { AddressInfo } from 'net'
import * as schedule from 'node-schedule'

Expand All @@ -16,7 +15,6 @@ import { startQueue } from './ingestion-queues/queue'
import { startJobQueueConsumer } from './job-queues/job-queue-consumer'
import { createMmdbServer, performMmdbStalenessCheck, prepareMmdb } from './services/mmdb'
import { startSchedule } from './services/schedule'
import { startFastifyInstance, stopFastifyInstance } from './services/web'

const { version } = require('../../package.json')

Expand All @@ -43,7 +41,6 @@ export async function startPluginsServer(

let pubSub: PubSub | undefined
let hub: Hub | undefined
let fastifyInstance: FastifyInstance | undefined
let actionsReloadJob: schedule.Job | undefined
let pingJob: schedule.Job | undefined
let piscinaStatsJob: schedule.Job | undefined
Expand All @@ -70,9 +67,6 @@ export async function startPluginsServer(
process.exit()
}
status.info('💤', ' Shutting down gracefully...')
if (fastifyInstance && !serverConfig?.DISABLE_WEB) {
await stopFastifyInstance(fastifyInstance!)
}
lastActivityCheck && clearInterval(lastActivityCheck)
await queue?.stop()
await pubSub?.stop()
Expand Down Expand Up @@ -132,9 +126,6 @@ export async function startPluginsServer(
}

piscina = makePiscina(serverConfig)
if (!hub.DISABLE_WEB) {
fastifyInstance = await startFastifyInstance(hub)
}

scheduleControl = await startSchedule(hub, piscina)
jobQueueConsumer = await startJobQueueConsumer(hub, piscina)
Expand Down
27 changes: 0 additions & 27 deletions src/main/services/web.ts

This file was deleted.

3 changes: 0 additions & 3 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,6 @@ export interface PluginsServerConfig extends Record<string, any> {
POSTHOG_REDIS_PORT: number
BASE_DIR: string
PLUGINS_RELOAD_PUBSUB_CHANNEL: string
DISABLE_WEB: boolean
WEB_PORT: number
WEB_HOSTNAME: string
LOG_LEVEL: LogLevel
SENTRY_DSN: string | null
STATSD_HOST: string | null
Expand Down
20 changes: 10 additions & 10 deletions tests/config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,27 @@ import { getDefaultConfig, overrideWithEnv } from '../src/config/config'
test('overrideWithEnv 1', () => {
const defaultConfig = getDefaultConfig()
const env = {
DISABLE_WEB: 'false',
WEB_PORT: '3008',
WEB_HOSTNAME: '0.0.0.0',
KAFKA_ENABLED: 'false',
TASK_TIMEOUT: '3008',
CLICKHOUSE_HOST: '0.0.0.0',
BASE_DIR: undefined,
}
const config = overrideWithEnv(getDefaultConfig(), env)

expect(config.DISABLE_WEB).toEqual(false)
expect(config.WEB_PORT).toEqual(3008)
expect(config.WEB_HOSTNAME).toEqual('0.0.0.0')
expect(config.KAFKA_ENABLED).toEqual(false)
expect(config.TASK_TIMEOUT).toEqual(3008)
expect(config.CLICKHOUSE_HOST).toEqual('0.0.0.0')
expect(config.BASE_DIR).toEqual(defaultConfig.BASE_DIR)
})

test('overrideWithEnv 2', () => {
const defaultConfig = getDefaultConfig()
const env = {
DISABLE_WEB: '1',
WEB_PORT: '3008.12',
KAFKA_ENABLED: '1',
TASK_TIMEOUT: '3008.12',
}
const config = overrideWithEnv(getDefaultConfig(), env)

expect(config.DISABLE_WEB).toEqual(true)
expect(config.WEB_PORT).toEqual(3008.12)
expect(config.KAFKA_ENABLED).toEqual(true)
expect(config.TASK_TIMEOUT).toEqual(3008.12)
})
Loading