mirror of
https://github.com/wekan/wekan.git
synced 2026-11-05 01:20:07 -05:00
FerretDB: default to polling-only on all platforms; OpLog is opt-in (#6503).
FerretDB v1 can tail an OpLog, but on the SQLite backend Meteor's tailable+awaitData OpLog tail keeps FerretDB CPU pinned (reporters saw ~190-390% even idle; a 2-core box maxed out) and a struggling tail also surfaces as 'oplog catching up took too long', stalling board and login-page loading. Despite the FerretDB-side mitigations (16 MiB capped oplog, 500ms awaitData poll, SQLite pragmas, CPU self-regulation) the peg persisted on real deployments, and the polling-only path reliably drops CPU to ~10%. So make POLLING the default on every launcher (snap wekan-control, bundle start-wekan.sh, docker wekan-entrypoint.sh + docker-compose.yml, windows start-wekan.bat, sandstorm start.js): WEKAN_FERRETDB_OPLOG now defaults false, docker-compose reactivity is 'polling' with MONGO_OPLOG_URL commented out. The OpLog machinery still exists and is opt-in via WEKAN_FERRETDB_OPLOG=true. The snap exposes it as a setting: 'snap set wekan wekan-ferretdb-oplog=true|false' (registered in snap-src/bin/config, default false). The calmer polling throttle (#6467/#6468) and SQLite pragma tuning keep poll-and-diff cheap. Tests: tests/ferretdbOplog.test.cjs updated to assert the polling-only default everywhere, the commented-out docker-compose MONGO_OPLOG_URL, the opt-in OpLog machinery still present, and the new wekan-ferretdb-oplog snap setting (default false). Thanks to xet7 !
This commit is contained in:
1 parent
2cde7bf25c
commit
b15d89dd0c
8 files changed
+107
-81
No files matched your search
+17
-12
@@ -142,13 +142,15 @@ services:
|
||||
# https://github.com/meteor/meteor/blob/release-3.5/v3-docs/docs/performance/change-streams-observer-driver.md#choosing-the-reactivity-driver-order
|
||||
# Keep oplog/polling fallback available for deployments that cannot use Change Streams:
|
||||
# https://github.com/wekan/wekan/issues/6307#issuecomment-4299349231
|
||||
# wekan/wekan#6480/#6481: FerretDB v1 now ships an OpLog (the ferretdb service
|
||||
# above runs with --repl-set-name=rs0), so prefer OpLog tailing and fall back
|
||||
# to polling — this is the main fix for FerretDB's high CPU on busy boards.
|
||||
# FerretDB has no MongoDB change streams. To force polling only, set both to
|
||||
# `polling` and comment out MONGO_OPLOG_URL below.
|
||||
- DEFAULT_METEOR_REACTIVITY_ORDER=oplog,polling
|
||||
- METEOR_REACTIVITY_ORDER=oplog,polling
|
||||
# wekan/wekan#6503/#6480/#6481: FerretDB v1 CAN tail an OpLog (the ferretdb
|
||||
# service above runs with --repl-set-name=rs0), but on the SQLite backend the
|
||||
# tailable+awaitData OpLog tail keeps FerretDB CPU pinned (~190–390% even idle)
|
||||
# and a struggling tail shows as "oplog catching up took too long" and stalls
|
||||
# loading, so the DEFAULT here is now POLLING ONLY. FerretDB has no MongoDB
|
||||
# change streams. To opt INTO OpLog tailing, set both to `oplog,polling` and
|
||||
# uncomment MONGO_OPLOG_URL in the wekan service below.
|
||||
- DEFAULT_METEOR_REACTIVITY_ORDER=polling
|
||||
- METEOR_REACTIVITY_ORDER=polling
|
||||
# uws does not work at s390x. sockjs works.
|
||||
#- DDP_TRANSPORT=uws
|
||||
- DDP_TRANSPORT=sockjs
|
||||
@@ -215,11 +217,14 @@ services:
|
||||
# - Latency from 50ms to 2000ms
|
||||
# Must configure MongoDB replica set first
|
||||
# See: https://blog.meteor.com/tuning-meteor-mongo-livedata-for-scalability-13fe9deb8908
|
||||
# FerretDB v1 emulates the OpLog via --repl-set-name=rs0 (set on the ferretdb
|
||||
# service above). This enables real-time DDP updates and stops the poll-and-diff
|
||||
# CPU burn (wekan/wekan#6480/#6481). To force polling only, comment this out and
|
||||
# set METEOR_REACTIVITY_ORDER=polling above.
|
||||
- MONGO_OPLOG_URL=mongodb://ferretdb:27017/local?replicaSet=rs0
|
||||
# FerretDB v1 CAN emulate the OpLog via --repl-set-name=rs0 (set on the
|
||||
# ferretdb service above), but on the SQLite backend the tail keeps FerretDB
|
||||
# CPU pinned and stalls loading (wekan/wekan#6503), so it is DISABLED by
|
||||
# default here. Merely SETTING MONGO_OPLOG_URL makes Meteor start an OpLog
|
||||
# tail regardless of the reactivity order (#6498), so it is commented out.
|
||||
# To opt INTO OpLog tailing, uncomment the next line AND set
|
||||
# METEOR_REACTIVITY_ORDER=oplog,polling above.
|
||||
#- MONGO_OPLOG_URL=mongodb://ferretdb:27017/local?replicaSet=rs0
|
||||
#---------------------------------------------------------------
|
||||
# ==== OPTIONAL: KADIRA PERFORMANCE MONITORING FOR METEOR ====
|
||||
# https://github.com/edemaine/kadira-compose
|
||||
|
||||
@@ -23,11 +23,11 @@ set "FERRETDB_SQLITE_DIR=%FILES%\db"
|
||||
if not defined PORT set "PORT=8080"
|
||||
if not defined ROOT_URL set "ROOT_URL=http://localhost:%PORT%"
|
||||
if not defined MONGO_URL set "MONGO_URL=mongodb://127.0.0.1:27017/wekan"
|
||||
REM #6480/#6481: FerretDB v1 now ships an OpLog (started below with
|
||||
REM --repl-set-name), so by default WeKan's Meteor TAILS the OpLog instead of
|
||||
REM poll-and-diff (fixes high FerretDB CPU on busy boards). Set
|
||||
REM WEKAN_FERRETDB_OPLOG=false to force the old polling-only behaviour.
|
||||
if not defined WEKAN_FERRETDB_OPLOG set "WEKAN_FERRETDB_OPLOG=true"
|
||||
REM #6503/#6480/#6481: FerretDB v1 CAN tail an OpLog (started below with
|
||||
REM --repl-set-name), but on the SQLite backend the tail keeps FerretDB CPU
|
||||
REM pinned (~190-390% even idle) and stalls loading, so the DEFAULT is now
|
||||
REM POLLING ONLY. Opt into OpLog tailing with WEKAN_FERRETDB_OPLOG=true.
|
||||
if not defined WEKAN_FERRETDB_OPLOG set "WEKAN_FERRETDB_OPLOG=false"
|
||||
if not defined WEKAN_FERRETDB_REPL_SET set "WEKAN_FERRETDB_REPL_SET=rs0"
|
||||
set "FERRET_REPL_ARG="
|
||||
if /I "%WEKAN_FERRETDB_OPLOG%"=="true" (
|
||||
|
||||
@@ -69,16 +69,16 @@ FERRET_PID=""
|
||||
stop_ferret() { [ -n "$FERRET_PID" ] && kill "$FERRET_PID" 2>/dev/null || true; }
|
||||
trap 'stop_ferret; exit 0' INT TERM
|
||||
|
||||
# #6480/#6481: FerretDB v1 now ships an OpLog (auto-created capped local.oplog.rs
|
||||
# + replica-set hello handshake — the ferretdb below is launched with
|
||||
# --repl-set-name). By default WeKan's Meteor TAILS the OpLog instead of
|
||||
# poll-and-diff, the main fix for FerretDB's high CPU on busy boards. Set
|
||||
# WEKAN_FERRETDB_OPLOG=false to force the old polling-only behaviour.
|
||||
# The polling settings remain the FALLBACK for queries Meteor cannot observe via
|
||||
# the OpLog. #6467/#6468: Meteor's defaults (re-poll 50 ms after any write, at
|
||||
# least every 10 s) hammer the database; calmer defaults re-poll at most every
|
||||
# 2 s / 30 s. Overridable by exporting different values before running this script.
|
||||
WEKAN_FERRETDB_OPLOG="${WEKAN_FERRETDB_OPLOG:-true}"
|
||||
# #6503/#6480/#6481: FerretDB v1 CAN tail an OpLog (auto-created capped
|
||||
# local.oplog.rs + replica-set hello handshake), but on the SQLite backend the
|
||||
# tailable+awaitData OpLog tail keeps FerretDB CPU pinned (reporters saw ~190–390%
|
||||
# even idle) and a struggling tail shows as "oplog catching up took too long" and
|
||||
# stalls loading, so the DEFAULT is now POLLING ONLY. Opt into OpLog tailing with
|
||||
# WEKAN_FERRETDB_OPLOG=true if you specifically want it.
|
||||
# The polling settings apply either way. #6467/#6468: Meteor's defaults (re-poll
|
||||
# 50 ms after any write, at least every 10 s) hammer the database; calmer defaults
|
||||
# re-poll at most every 2 s / 30 s. Overridable by exporting values before running.
|
||||
WEKAN_FERRETDB_OPLOG="${WEKAN_FERRETDB_OPLOG:-false}"
|
||||
WEKAN_FERRETDB_REPL_SET="${WEKAN_FERRETDB_REPL_SET:-rs0}"
|
||||
FERRET_REPL_ARG=""
|
||||
if [ "$want_ferret" = true ]; then
|
||||
|
||||
@@ -47,12 +47,13 @@ if [ "$want_ferret" = true ]; then
|
||||
fi
|
||||
export MONGO_URL="${MONGO_URL:-mongodb://$FERRETDB_LISTEN_ADDR/wekan}"
|
||||
mkdir -p "$FERRETDB_SQLITE_DIR"
|
||||
# #6480/#6481: FerretDB v1 now ships an OpLog (auto-created capped
|
||||
# local.oplog.rs + replica-set hello handshake), launched below with
|
||||
# --repl-set-name. By default WeKan's Meteor TAILS the OpLog instead of
|
||||
# poll-and-diff — the main fix for FerretDB's high CPU on busy boards. Set
|
||||
# WEKAN_FERRETDB_OPLOG=false to force the old polling-only behaviour.
|
||||
WEKAN_FERRETDB_OPLOG="${WEKAN_FERRETDB_OPLOG:-true}"
|
||||
# #6503/#6480/#6481: FerretDB v1 CAN tail an OpLog (auto-created capped
|
||||
# local.oplog.rs + replica-set hello handshake), but on the SQLite backend the
|
||||
# tailable+awaitData tail keeps FerretDB CPU pinned (~190–390% even idle) and a
|
||||
# struggling tail shows as "oplog catching up took too long" and stalls loading,
|
||||
# so the DEFAULT is now POLLING ONLY. Opt into OpLog tailing with
|
||||
# WEKAN_FERRETDB_OPLOG=true if you specifically want it.
|
||||
WEKAN_FERRETDB_OPLOG="${WEKAN_FERRETDB_OPLOG:-false}"
|
||||
REPL_SET_NAME="${WEKAN_FERRETDB_REPL_SET:-rs0}"
|
||||
if [ "$WEKAN_FERRETDB_OPLOG" = "true" ]; then
|
||||
export MONGO_OPLOG_URL="${MONGO_OPLOG_URL:-mongodb://$FERRETDB_LISTEN_ADDR/local?replicaSet=$REPL_SET_NAME}"
|
||||
|
||||
@@ -54,13 +54,14 @@ const DB_PORT = '4001'; // FerretDB stead
|
||||
const SRC_PORT = '4003'; // mongod 3.0 (migration source)
|
||||
const NISCU_PORT = '4004'; // niscud (niscu→3.0 source)
|
||||
|
||||
// #6480/#6481: FerretDB v1 ships an OpLog (auto-created capped local.oplog.rs +
|
||||
// replica-set hello handshake). Run the STEADY-STATE FerretDB with a replica-set
|
||||
// name and point WeKan at it so Meteor tails the OpLog instead of poll-and-diff.
|
||||
// Polling stays the fallback (METEOR_REACTIVITY_ORDER=oplog,polling → OpLog only
|
||||
// when tailing works). WEKAN_FERRETDB_OPLOG=false forces polling only. The
|
||||
// transient migration-target FerretDB above stays OpLog-free (no --repl-set-name).
|
||||
const FERRET_OPLOG = process.env.WEKAN_FERRETDB_OPLOG !== 'false';
|
||||
// #6503/#6480/#6481: FerretDB v1 CAN tail an OpLog (auto-created capped
|
||||
// local.oplog.rs + replica-set hello handshake), but on the SQLite backend the
|
||||
// tailable+awaitData tail keeps FerretDB CPU pinned (~190–390% even idle) and a
|
||||
// struggling tail shows as "oplog catching up took too long" and stalls loading,
|
||||
// so the DEFAULT is now POLLING ONLY. Opt into OpLog tailing with
|
||||
// WEKAN_FERRETDB_OPLOG=true. The transient migration-target FerretDB above stays
|
||||
// OpLog-free (no --repl-set-name) regardless.
|
||||
const FERRET_OPLOG = process.env.WEKAN_FERRETDB_OPLOG === 'true';
|
||||
const REPL_SET_NAME = process.env.WEKAN_FERRETDB_REPL_SET || 'rs0';
|
||||
|
||||
function ensureDirs() {
|
||||
|
||||
+5
-1
@@ -3,7 +3,7 @@
|
||||
# All supported keys are defined here together with descriptions and default values
|
||||
|
||||
# list of supported keys
|
||||
keys="DEBUG DATABASE DDP_TRANSPORT METEOR_REACTIVITY_ORDER MONGO_LOG_DESTINATION MONGO_URL MONGO_OPLOG_URL MONGODB_BIND_UNIX_SOCKET MONGODB_BIND_IP MONGODB_PORT MAIL_URL MAIL_FROM MAIL_SERVICE MAIL_SERVICE_USER MAIL_SERVICE_PASSWORD ROOT_URL PORT DISABLE_MONGODB CADDY_ENABLED CADDY_BIND_PORT WITH_API RICHER_CARD_COMMENT_EDITOR CARDS_LOADING CARD_OPENED_WEBHOOK_ENABLED ACCOUNTS_LOCKOUT_KNOWN_USERS_FAILURES_BEFORE ACCOUNTS_LOCKOUT_KNOWN_USERS_PERIOD ACCOUNTS_LOCKOUT_KNOWN_USERS_FAILURE_WINDOW ACCOUNTS_LOCKOUT_UNKNOWN_USERS_FAILURES_BERORE ACCOUNTS_LOCKOUT_UNKNOWN_USERS_LOCKOUT_PERIOD ACCOUNTS_LOCKOUT_UNKNOWN_USERS_FAILURE_WINDOW ACCOUNTS_COMMON_LOGIN_EXPIRATION_IN_DAYS ATTACHMENTS_UPLOAD_EXTERNAL_PROGRAM ATTACHMENTS_UPLOAD_MIME_TYPES ATTACHMENTS_UPLOAD_MAX_SIZE AVATARS_UPLOAD_EXTERNAL_PROGRAM AVATARS_UPLOAD_MIME_TYPES AVATARS_UPLOAD_MAX_SIZE MAX_IMAGE_PIXEL IMAGE_COMPRESS_RATIO BIGEVENTS_PATTERN NOTIFICATION_TRAY_AFTER_READ_DAYS_BEFORE_REMOVE NOTIFY_DUE_DAYS_BEFORE_AND_AFTER NOTIFY_DUE_AT_HOUR_OF_DAY DEFAULT_BOARD_ID EMAIL_NOTIFICATION_TIMEOUT CORS CORS_ALLOW_HEADERS CORS_EXPOSE_HEADERS MATOMO_ADDRESS MATOMO_SITE_ID MATOMO_DO_NOT_TRACK MATOMO_WITH_USERNAME METRICS_ALLOWED_IP_ADDRESSES BROWSER_POLICY_ENABLED TRUSTED_URL WEBHOOKS_ATTRIBUTES OAUTH2_ENABLED OIDC_REDIRECTION_ENABLED OAUTH2_CA_CERT OAUTH2_LOGIN_STYLE OAUTH2_CLIENT_ID OAUTH2_SECRET OAUTH2_SERVER_URL OAUTH2_AUTH_ENDPOINT OAUTH2_USERINFO_ENDPOINT OAUTH2_TOKEN_ENDPOINT OAUTH2_LOGOUT_ENDPOINT OAUTH2_ID_MAP OAUTH2_USERNAME_MAP OAUTH2_FULLNAME_MAP OAUTH2_ID_TOKEN_WHITELIST_FIELDS OAUTH2_EMAIL_MAP OAUTH2_REQUEST_PERMISSIONS OAUTH2_ADFS_ENABLED OAUTH2_B2C_ENABLED OAUTH2_MERGE_EXISTING_USERS LDAP_ENABLE LDAP_PORT LDAP_HOST LDAP_AD_SIMPLE_AUTH LDAP_BASEDN LDAP_LOGIN_FALLBACK LDAP_RECONNECT LDAP_TIMEOUT LDAP_IDLE_TIMEOUT LDAP_CONNECT_TIMEOUT LDAP_AUTHENTIFICATION LDAP_AUTHENTIFICATION_USERDN LDAP_AUTHENTIFICATION_PASSWORD LDAP_LOG_ENABLED LDAP_BACKGROUND_SYNC LDAP_BACKGROUND_SYNC_INTERVAL LDAP_BACKGROUND_SYNC_KEEP_EXISTANT_USERS_UPDATED LDAP_BACKGROUND_SYNC_IMPORT_NEW_USERS LDAP_ENCRYPTION LDAP_CA_CERT LDAP_REJECT_UNAUTHORIZED LDAP_USER_AUTHENTICATION LDAP_USER_AUTHENTICATION_FIELD LDAP_USER_SEARCH_FILTER LDAP_USER_SEARCH_SCOPE LDAP_USER_SEARCH_FIELD LDAP_SEARCH_PAGE_SIZE LDAP_SEARCH_SIZE_LIMIT LDAP_GROUP_FILTER_ENABLE LDAP_GROUP_FILTER_OBJECTCLASS LDAP_GROUP_FILTER_GROUP_ID_ATTRIBUTE LDAP_GROUP_FILTER_GROUP_MEMBER_ATTRIBUTE LDAP_GROUP_FILTER_GROUP_MEMBER_FORMAT LDAP_GROUP_FILTER_GROUP_NAME LDAP_UNIQUE_IDENTIFIER_FIELD LDAP_UTF8_NAMES_SLUGIFY LDAP_USERNAME_FIELD LDAP_FULLNAME_FIELD LDAP_MERGE_EXISTING_USERS LDAP_SYNC_USER_DATA LDAP_SYNC_USER_DATA_FIELDMAP LDAP_SYNC_GROUP_ROLES LDAP_DEFAULT_DOMAIN LDAP_EMAIL_MATCH_ENABLE LDAP_EMAIL_MATCH_REQUIRE LDAP_EMAIL_MATCH_VERIFIED LDAP_EMAIL_FIELD LDAP_SYNC_ADMIN_STATUS LDAP_SYNC_ADMIN_GROUPS HEADER_LOGIN_ID HEADER_LOGIN_FIRSTNAME HEADER_LOGIN_LASTNAME HEADER_LOGIN_EMAIL HEADER_LOGIN_TRUSTED_IPS HEADER_LOGIN_TRUSTED_PROXIES LOGOUT_WITH_TIMER LOGOUT_IN LOGOUT_ON_HOURS LOGOUT_ON_MINUTES DEFAULT_AUTHENTICATION_METHOD PASSWORD_LOGIN_ENABLED CAS_ENABLED CAS_BASE_URL CAS_LOGIN_URL CAS_VALIDATE_URL SAML_ENABLED SAML_PROVIDER SAML_ENTRYPOINT SAML_ISSUER SAML_CERT SAML_IDPSLO_REDIRECTURL SAML_PRIVATE_KEYFILE SAML_PUBLIC_CERTFILE SAML_IDENTIFIER_FORMAT SAML_LOCAL_PROFILE_MATCH_ATTRIBUTE SAML_ATTRIBUTES ORACLE_OIM_ENABLED RESULTS_PER_PAGE WAIT_SPINNER NODE_OPTIONS LDAP_AUTHENTIFICATION_PASSWORD_FILE OAUTH2_SECRET_FILE MAIL_SERVICE_PASSWORD_FILE MONGO_PASSWORD_FILE S3 S3_SECRET_FILE OAUTH2_AUTO_REGISTRATION OAUTH2_ADMIN_GROUPS NOTIFY_ON_ASSIGN LDAP_BACKGROUND_SYNC_DISABLE_NONEXISTANT_USERS LDAP_SYNC_ORGANIZATIONS LDAP_SYNC_ORGANIZATIONS_GROUPS LDAP_SYNC_TEAMS LDAP_SYNC_TEAMS_GROUPS"
|
||||
keys="DEBUG DATABASE WEKAN_FERRETDB_OPLOG DDP_TRANSPORT METEOR_REACTIVITY_ORDER MONGO_LOG_DESTINATION MONGO_URL MONGO_OPLOG_URL MONGODB_BIND_UNIX_SOCKET MONGODB_BIND_IP MONGODB_PORT MAIL_URL MAIL_FROM MAIL_SERVICE MAIL_SERVICE_USER MAIL_SERVICE_PASSWORD ROOT_URL PORT DISABLE_MONGODB CADDY_ENABLED CADDY_BIND_PORT WITH_API RICHER_CARD_COMMENT_EDITOR CARDS_LOADING CARD_OPENED_WEBHOOK_ENABLED ACCOUNTS_LOCKOUT_KNOWN_USERS_FAILURES_BEFORE ACCOUNTS_LOCKOUT_KNOWN_USERS_PERIOD ACCOUNTS_LOCKOUT_KNOWN_USERS_FAILURE_WINDOW ACCOUNTS_LOCKOUT_UNKNOWN_USERS_FAILURES_BERORE ACCOUNTS_LOCKOUT_UNKNOWN_USERS_LOCKOUT_PERIOD ACCOUNTS_LOCKOUT_UNKNOWN_USERS_FAILURE_WINDOW ACCOUNTS_COMMON_LOGIN_EXPIRATION_IN_DAYS ATTACHMENTS_UPLOAD_EXTERNAL_PROGRAM ATTACHMENTS_UPLOAD_MIME_TYPES ATTACHMENTS_UPLOAD_MAX_SIZE AVATARS_UPLOAD_EXTERNAL_PROGRAM AVATARS_UPLOAD_MIME_TYPES AVATARS_UPLOAD_MAX_SIZE MAX_IMAGE_PIXEL IMAGE_COMPRESS_RATIO BIGEVENTS_PATTERN NOTIFICATION_TRAY_AFTER_READ_DAYS_BEFORE_REMOVE NOTIFY_DUE_DAYS_BEFORE_AND_AFTER NOTIFY_DUE_AT_HOUR_OF_DAY DEFAULT_BOARD_ID EMAIL_NOTIFICATION_TIMEOUT CORS CORS_ALLOW_HEADERS CORS_EXPOSE_HEADERS MATOMO_ADDRESS MATOMO_SITE_ID MATOMO_DO_NOT_TRACK MATOMO_WITH_USERNAME METRICS_ALLOWED_IP_ADDRESSES BROWSER_POLICY_ENABLED TRUSTED_URL WEBHOOKS_ATTRIBUTES OAUTH2_ENABLED OIDC_REDIRECTION_ENABLED OAUTH2_CA_CERT OAUTH2_LOGIN_STYLE OAUTH2_CLIENT_ID OAUTH2_SECRET OAUTH2_SERVER_URL OAUTH2_AUTH_ENDPOINT OAUTH2_USERINFO_ENDPOINT OAUTH2_TOKEN_ENDPOINT OAUTH2_LOGOUT_ENDPOINT OAUTH2_ID_MAP OAUTH2_USERNAME_MAP OAUTH2_FULLNAME_MAP OAUTH2_ID_TOKEN_WHITELIST_FIELDS OAUTH2_EMAIL_MAP OAUTH2_REQUEST_PERMISSIONS OAUTH2_ADFS_ENABLED OAUTH2_B2C_ENABLED OAUTH2_MERGE_EXISTING_USERS LDAP_ENABLE LDAP_PORT LDAP_HOST LDAP_AD_SIMPLE_AUTH LDAP_BASEDN LDAP_LOGIN_FALLBACK LDAP_RECONNECT LDAP_TIMEOUT LDAP_IDLE_TIMEOUT LDAP_CONNECT_TIMEOUT LDAP_AUTHENTIFICATION LDAP_AUTHENTIFICATION_USERDN LDAP_AUTHENTIFICATION_PASSWORD LDAP_LOG_ENABLED LDAP_BACKGROUND_SYNC LDAP_BACKGROUND_SYNC_INTERVAL LDAP_BACKGROUND_SYNC_KEEP_EXISTANT_USERS_UPDATED LDAP_BACKGROUND_SYNC_IMPORT_NEW_USERS LDAP_ENCRYPTION LDAP_CA_CERT LDAP_REJECT_UNAUTHORIZED LDAP_USER_AUTHENTICATION LDAP_USER_AUTHENTICATION_FIELD LDAP_USER_SEARCH_FILTER LDAP_USER_SEARCH_SCOPE LDAP_USER_SEARCH_FIELD LDAP_SEARCH_PAGE_SIZE LDAP_SEARCH_SIZE_LIMIT LDAP_GROUP_FILTER_ENABLE LDAP_GROUP_FILTER_OBJECTCLASS LDAP_GROUP_FILTER_GROUP_ID_ATTRIBUTE LDAP_GROUP_FILTER_GROUP_MEMBER_ATTRIBUTE LDAP_GROUP_FILTER_GROUP_MEMBER_FORMAT LDAP_GROUP_FILTER_GROUP_NAME LDAP_UNIQUE_IDENTIFIER_FIELD LDAP_UTF8_NAMES_SLUGIFY LDAP_USERNAME_FIELD LDAP_FULLNAME_FIELD LDAP_MERGE_EXISTING_USERS LDAP_SYNC_USER_DATA LDAP_SYNC_USER_DATA_FIELDMAP LDAP_SYNC_GROUP_ROLES LDAP_DEFAULT_DOMAIN LDAP_EMAIL_MATCH_ENABLE LDAP_EMAIL_MATCH_REQUIRE LDAP_EMAIL_MATCH_VERIFIED LDAP_EMAIL_FIELD LDAP_SYNC_ADMIN_STATUS LDAP_SYNC_ADMIN_GROUPS HEADER_LOGIN_ID HEADER_LOGIN_FIRSTNAME HEADER_LOGIN_LASTNAME HEADER_LOGIN_EMAIL HEADER_LOGIN_TRUSTED_IPS HEADER_LOGIN_TRUSTED_PROXIES LOGOUT_WITH_TIMER LOGOUT_IN LOGOUT_ON_HOURS LOGOUT_ON_MINUTES DEFAULT_AUTHENTICATION_METHOD PASSWORD_LOGIN_ENABLED CAS_ENABLED CAS_BASE_URL CAS_LOGIN_URL CAS_VALIDATE_URL SAML_ENABLED SAML_PROVIDER SAML_ENTRYPOINT SAML_ISSUER SAML_CERT SAML_IDPSLO_REDIRECTURL SAML_PRIVATE_KEYFILE SAML_PUBLIC_CERTFILE SAML_IDENTIFIER_FORMAT SAML_LOCAL_PROFILE_MATCH_ATTRIBUTE SAML_ATTRIBUTES ORACLE_OIM_ENABLED RESULTS_PER_PAGE WAIT_SPINNER NODE_OPTIONS LDAP_AUTHENTIFICATION_PASSWORD_FILE OAUTH2_SECRET_FILE MAIL_SERVICE_PASSWORD_FILE MONGO_PASSWORD_FILE S3 S3_SECRET_FILE OAUTH2_AUTO_REGISTRATION OAUTH2_ADMIN_GROUPS NOTIFY_ON_ASSIGN LDAP_BACKGROUND_SYNC_DISABLE_NONEXISTANT_USERS LDAP_SYNC_ORGANIZATIONS LDAP_SYNC_ORGANIZATIONS_GROUPS LDAP_SYNC_TEAMS LDAP_SYNC_TEAMS_GROUPS"
|
||||
|
||||
#-------------------- CHANGE STREAMS --------------------
|
||||
# https://forums.meteor.com/t/meteor-3-5-beta-change-streams-performance-improvements/64461#change-streams-setup-3
|
||||
@@ -114,6 +114,10 @@ DESCRIPTION_DATABASE="Database backend: 'mongodb' (default) or 'ferretdb' (Ferre
|
||||
DEFAULT_DATABASE="mongodb"
|
||||
KEY_DATABASE="database"
|
||||
|
||||
DESCRIPTION_WEKAN_FERRETDB_OPLOG="FerretDB reactivity mode. 'false' (default) = polling only, which keeps FerretDB CPU low; 'true' = tail the FerretDB OpLog (real-time), but on the SQLite backend the tail can pin FerretDB CPU and stall loading (wekan/wekan#6503). Only applies when database=ferretdb. Force polling: snap set ${SNAP_NAME} wekan-ferretdb-oplog=false ; opt into OpLog: snap set ${SNAP_NAME} wekan-ferretdb-oplog=true"
|
||||
DEFAULT_WEKAN_FERRETDB_OPLOG="false"
|
||||
KEY_WEKAN_FERRETDB_OPLOG="wekan-ferretdb-oplog"
|
||||
|
||||
DESCRIPTION_CADDY_ENABLED="Enable caddy service (caddy - Every Site on HTTPS) personal license for non-commercial use only, see https://caddyserver.com/products/licenses . Set to 'true' to enable caddy\n\t\tcaddy settings are handled through $SNAP_COMMON/Caddyfile"
|
||||
DEFAULT_CADDY_ENABLED="false"
|
||||
KEY_CADDY_ENABLED="caddy-enabled"
|
||||
|
||||
+14
-12
@@ -86,20 +86,22 @@ else
|
||||
fi
|
||||
fi
|
||||
|
||||
# #6480/#6481: FerretDB v1 now ships an OpLog (auto-created capped local.oplog.rs
|
||||
# + replica-set hello handshake — see bin/ferretdb-control, which launches with
|
||||
# --repl-set-name). So by default WeKan's Meteor TAILS the OpLog instead of
|
||||
# poll-and-diff, which is the main fix for FerretDB's high CPU on busy boards.
|
||||
# Enabled by default; set WEKAN_FERRETDB_OPLOG=false (snap set) to force the old
|
||||
# polling-only behaviour if OpLog tailing ever misbehaves.
|
||||
# #6503/#6480/#6481: FerretDB v1 CAN tail an OpLog (auto-created capped
|
||||
# local.oplog.rs + replica-set hello handshake — see bin/ferretdb-control), but
|
||||
# on the SQLite backend Meteor's tailable+awaitData OpLog tail keeps FerretDB CPU
|
||||
# pinned (reporters saw ~190–390% even idle; deleting local.sqlite* dropped it to
|
||||
# ~10%), and a struggling tail also shows up as "oplog catching up took too long"
|
||||
# and stalls board/login loading. So the DEFAULT is now POLLING ONLY. With the
|
||||
# calmer polling defaults (#6467/#6468) and the SQLite pragma tuning, poll-and-diff
|
||||
# is cheap. Opt into OpLog tailing with WEKAN_FERRETDB_OPLOG=true (snap set) if you
|
||||
# specifically want it and have verified it stays calm on your data.
|
||||
#
|
||||
# The polling settings below still apply as the FALLBACK for the queries Meteor
|
||||
# cannot observe through the OpLog (and when OpLog is disabled). #6467/#6468: the
|
||||
# Meteor defaults (re-poll 50 ms after any write, at least every 10 s) hammered
|
||||
# FerretDB; calmer defaults re-poll at most every 2 s / 30 s. Own writes still
|
||||
# show instantly (local cache); only OTHER users' changes wait up to ~2 s.
|
||||
# The polling settings below apply either way (they are also the OpLog fallback).
|
||||
# #6467/#6468: the Meteor defaults (re-poll 50 ms after any write, at least every
|
||||
# 10 s) hammered FerretDB; calmer defaults re-poll at most every 2 s / 30 s. Own
|
||||
# writes still show instantly (local cache); only OTHER users' changes wait ~2 s.
|
||||
if [ "ferretdb" = "${DATABASE}" ]; then
|
||||
WEKAN_FERRETDB_OPLOG="${WEKAN_FERRETDB_OPLOG:-true}"
|
||||
WEKAN_FERRETDB_OPLOG="${WEKAN_FERRETDB_OPLOG:-false}"
|
||||
if [ "true" = "${WEKAN_FERRETDB_OPLOG}" ]; then
|
||||
if [ -z "${MONGO_OPLOG_URL}" ]; then
|
||||
REPL_SET_NAME="${WEKAN_FERRETDB_REPL_SET:-rs0}"
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
'use strict';
|
||||
|
||||
// Guards for the FerretDB OpLog + data-reduction changes (#6480/#6481).
|
||||
// Guards for the FerretDB OpLog + data-reduction changes (#6503/#6480/#6481).
|
||||
//
|
||||
// With FerretDB there is no MongoDB oplog, so Meteor observed every live query by
|
||||
// poll-and-diff, pinning FerretDB CPU at 100-390% on busy boards. FerretDB v1 now
|
||||
// ships an OpLog (auto-created capped local.oplog.rs + replica-set hello
|
||||
// handshake), so every FerretDB launch path must (a) start ferretdb with
|
||||
// --repl-set-name so the OpLog exists and the server advertises the replica set,
|
||||
// and (b) point WeKan at it via MONGO_OPLOG_URL so Meteor TAILS the OpLog instead
|
||||
// of polling — with a WEKAN_FERRETDB_OPLOG kill-switch back to polling. Also
|
||||
// asserts the oversized activity page was trimmed.
|
||||
// FerretDB v1 CAN tail an OpLog (auto-created capped local.oplog.rs + replica-set
|
||||
// hello handshake), but on the SQLite backend the tailable+awaitData tail pins
|
||||
// FerretDB CPU (~190-390% even idle) and a struggling tail stalls loading
|
||||
// ("oplog catching up took too long"), so #6503 makes POLLING the DEFAULT on every
|
||||
// platform. The OpLog machinery still EXISTS and is opt-in via
|
||||
// WEKAN_FERRETDB_OPLOG=true. These guards assert: (a) the default is polling only
|
||||
// (WEKAN_FERRETDB_OPLOG defaults false; docker-compose reactivity is `polling` and
|
||||
// MONGO_OPLOG_URL is commented out); (b) when opted in, ferretdb still launches
|
||||
// with --repl-set-name and WeKan is pointed at MONGO_OPLOG_URL with polling as the
|
||||
// fallback; and (c) the oversized activity page was trimmed.
|
||||
//
|
||||
// Run: node tests/ferretdbOplog.test.cjs
|
||||
|
||||
@@ -58,33 +60,42 @@ test('windows start-wekan.bat passes a repl-set arg to ferretdb.exe', () => {
|
||||
assert.ok(/ferretdb\.exe.*%FERRET_REPL_ARG%/.test(src), 'passes it on the ferretdb.exe line');
|
||||
});
|
||||
|
||||
// ── WeKan points at the OpLog by default (with a kill-switch) ────────────────
|
||||
test('snap wekan-control sets MONGO_OPLOG_URL for FerretDB, gated by WEKAN_FERRETDB_OPLOG', () => {
|
||||
// ── #6503: FerretDB is POLLING ONLY by default; OpLog is opt-in ──────────────
|
||||
test('snap wekan-control: polling-only default for FerretDB, OpLog opt-in', () => {
|
||||
const src = read('snap-src/bin/wekan-control');
|
||||
assert.ok(/WEKAN_FERRETDB_OPLOG:-true/.test(src), 'OpLog on by default');
|
||||
assert.ok(/export MONGO_OPLOG_URL="mongodb:\/\/.*\/local\?replicaSet=/.test(src), 'sets oplog url to local?replicaSet');
|
||||
assert.ok(/"true" = "\$\{WEKAN_FERRETDB_OPLOG\}"/.test(src), 'kill-switch check present');
|
||||
assert.ok(/WEKAN_FERRETDB_OPLOG:-false/.test(src), 'OpLog OFF by default (polling only)');
|
||||
assert.ok(/export MONGO_OPLOG_URL="mongodb:\/\/.*\/local\?replicaSet=/.test(src), 'still sets oplog url when opted in');
|
||||
assert.ok(/"true" = "\$\{WEKAN_FERRETDB_OPLOG\}"/.test(src), 'opt-in check present');
|
||||
});
|
||||
test('bundle start-wekan.sh sets MONGO_OPLOG_URL by default, kill-switch WEKAN_FERRETDB_OPLOG', () => {
|
||||
test('snap config registers wekan-ferretdb-oplog (default false, snap set toggle)', () => {
|
||||
const src = read('snap-src/bin/config');
|
||||
assert.ok(/\bWEKAN_FERRETDB_OPLOG\b/.test(src.match(/keys="[^"]*"/)[0]), 'listed in the settings keys');
|
||||
assert.ok(/DEFAULT_WEKAN_FERRETDB_OPLOG="false"/.test(src), 'defaults to false (polling)');
|
||||
assert.ok(/KEY_WEKAN_FERRETDB_OPLOG="wekan-ferretdb-oplog"/.test(src), 'snap set key is wekan-ferretdb-oplog');
|
||||
});
|
||||
test('bundle start-wekan.sh: polling-only default, OpLog opt-in via WEKAN_FERRETDB_OPLOG=true', () => {
|
||||
const src = read('releases/ferretdb/start-wekan.sh');
|
||||
assert.ok(/WEKAN_FERRETDB_OPLOG="\$\{WEKAN_FERRETDB_OPLOG:-true\}"/.test(src), 'default true');
|
||||
assert.ok(/WEKAN_FERRETDB_OPLOG="\$\{WEKAN_FERRETDB_OPLOG:-false\}"/.test(src), 'default false');
|
||||
assert.ok(/export MONGO_OPLOG_URL="\$\{MONGO_OPLOG_URL:-mongodb:\/\/\$FERRETDB_LISTEN_ADDR\/local\?replicaSet=/.test(src));
|
||||
});
|
||||
test('docker wekan-entrypoint.sh sets MONGO_OPLOG_URL, kill-switch present', () => {
|
||||
test('docker wekan-entrypoint.sh: polling-only default, OpLog opt-in', () => {
|
||||
const src = read('releases/ferretdb/wekan-entrypoint.sh');
|
||||
assert.ok(/WEKAN_FERRETDB_OPLOG="\$\{WEKAN_FERRETDB_OPLOG:-true\}"/.test(src), 'default true');
|
||||
assert.ok(/WEKAN_FERRETDB_OPLOG="\$\{WEKAN_FERRETDB_OPLOG:-false\}"/.test(src), 'default false');
|
||||
assert.ok(/export MONGO_OPLOG_URL="\$\{MONGO_OPLOG_URL:-mongodb:\/\/\$FERRETDB_LISTEN_ADDR\/local\?replicaSet=/.test(src));
|
||||
});
|
||||
test('docker-compose prefers oplog reactivity + sets MONGO_OPLOG_URL (uncommented)', () => {
|
||||
test('docker-compose: polling-only reactivity by default + MONGO_OPLOG_URL commented out', () => {
|
||||
const src = read('docker-compose.yml');
|
||||
assert.ok(/METEOR_REACTIVITY_ORDER=oplog,polling/.test(src), 'reactivity prefers oplog then polling');
|
||||
// the MONGO_OPLOG_URL line must be active (not commented out)
|
||||
assert.ok(/\n\s*- MONGO_OPLOG_URL=mongodb:\/\/ferretdb:27017\/local\?replicaSet=rs0/.test(src),
|
||||
'MONGO_OPLOG_URL must be an active env line, not commented');
|
||||
assert.ok(/METEOR_REACTIVITY_ORDER=polling/.test(src), 'reactivity is polling by default');
|
||||
// the MONGO_OPLOG_URL line must NOT be active (commented out for polling-only)
|
||||
assert.ok(!/\n\s*- MONGO_OPLOG_URL=mongodb:\/\/ferretdb:27017/.test(src),
|
||||
'MONGO_OPLOG_URL must NOT be an active env line');
|
||||
assert.ok(/#\s*-\s*MONGO_OPLOG_URL=mongodb:\/\/ferretdb:27017\/local\?replicaSet=rs0/.test(src),
|
||||
'the opt-in MONGO_OPLOG_URL line is present but commented');
|
||||
});
|
||||
test('windows start-wekan.bat sets MONGO_OPLOG_URL under the kill-switch', () => {
|
||||
test('windows start-wekan.bat: polling-only default, OpLog opt-in', () => {
|
||||
const src = read('releases/ferretdb/start-wekan.bat');
|
||||
assert.ok(/WEKAN_FERRETDB_OPLOG%"=="true"/.test(src), 'gated on the kill-switch');
|
||||
assert.ok(/set "WEKAN_FERRETDB_OPLOG=false"/.test(src), 'default false');
|
||||
assert.ok(/WEKAN_FERRETDB_OPLOG%"=="true"/.test(src), 'opt-in branch gated on =true');
|
||||
assert.ok(/MONGO_OPLOG_URL=mongodb:\/\/127\.0\.0\.1:27017\/local\?replicaSet=/.test(src));
|
||||
});
|
||||
|
||||
@@ -107,7 +118,7 @@ test('#6498: polling mode UNSETS MONGO_OPLOG_URL so Meteor never tails the OpLog
|
||||
// OpLog only when tailing actually works, else polling — so a broken/absent
|
||||
// OpLog never stops WeKan starting. Every FerretDB launch path must keep polling
|
||||
// last (like the MongoDB "changeStreams,oplog,polling" default).
|
||||
test('every FerretDB launch path keeps polling as the reactivity fallback (oplog,polling)', () => {
|
||||
test('every FerretDB launch path always has polling (as the default or the OpLog fallback)', () => {
|
||||
for (const f of [
|
||||
'snap-src/bin/wekan-control',
|
||||
'releases/ferretdb/start-wekan.sh',
|
||||
@@ -117,8 +128,10 @@ test('every FerretDB launch path keeps polling as the reactivity fallback (oplog
|
||||
'sandstorm-src/start.js',
|
||||
]) {
|
||||
const src = read(f);
|
||||
assert.ok(/METEOR_REACTIVITY_ORDER[^\n]*oplog,polling/.test(src),
|
||||
`${f} must set METEOR_REACTIVITY_ORDER to oplog,polling (polling fallback)`);
|
||||
// Default is now polling-only (METEOR_REACTIVITY_ORDER=polling); the opt-in
|
||||
// OpLog branch keeps polling last (oplog,polling). Both contain "polling".
|
||||
assert.ok(/METEOR_REACTIVITY_ORDER[^\n]*polling/.test(src),
|
||||
`${f} must keep polling available in METEOR_REACTIVITY_ORDER`);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Reference in new issue
Block a user