mirror of
https://github.com/penpot/penpot.git
synced 2026-10-29 22:10:34 +00:00
A save whose changes failed validation was rejected as a whole: autosave stopped, the edits made after it piled up unsent, and a reload lost them all, the valid ones included. The frontend now sends each commit of a save as its own group with its commit id (:changes-with-metadata). When applying and validating all of them at once fails, the backend searches by bisection for the first commit that fails, keeps the commits before it and answers with :rejected (that commit and every later one). Only the kept changes are stored, snapshotted and broadcast, so other users never see the rejected ones. Flat :changes and groups without ids stay all-or-nothing; database and network errors still fail the whole request. A rejection without an error type is reported as an internal error. The frontend rolls the file back to what the server holds: it undoes every pending commit of that file, applies again the remote changes that arrived meanwhile, and redoes the kept commits. Undoing only the rejected commits would write stale values over a peer's later change to the same attribute. The rejected and later commits leave the queue, the buffer and the undo history, and a warning that hides after ten seconds tells the user. The pure bookkeeping lives in app.main.data.persistence.commits. The pending notice of a commit the rollback dropped no longer leaves the save status at pending, which made "Pin this version" hang and fail. Debug tools drive these cases by hand: debug.commitInvalidChange() makes a save fail validation, holdSaves() delays the answers, failNextSave() and failNextRollback() fail them on purpose (backend flag debug-save-faults), and persistenceState() shows the queue.
130 lines
4.4 KiB
Bash
130 lines
4.4 KiB
Bash
#!/usr/bin/env bash
|
|
|
|
export PENPOT_ADMIN_CONSOLE_SHARED_KEY=super-secret-nitrate-api-key
|
|
export PENPOT_EXPORTER_SHARED_KEY=super-secret-exporter-api-key
|
|
export PENPOT_NEXUS_SHARED_KEY=super-secret-nexus-api-key
|
|
export PENPOT_SECRET_KEY=super-secret-devenv-key
|
|
export PENPOT_MEDIA_PROCESSOR_SHARED_KEY=super-secret-media-processor-key
|
|
|
|
# DEPRECATED: only used for subscriptions
|
|
export PENPOT_MANAGEMENT_API_KEY=super-secret-management-api-key
|
|
|
|
# Runtime config that varies per devenv instance (PENPOT_HOST, PENPOT_PUBLIC_URI,
|
|
# PENPOT_DATABASE_*, PENPOT_REDIS_URI, PENPOT_OBJECTS_STORAGE_*, AWS_*) is owned by
|
|
# docker/devenv/defaults.env and injected via the main service's env block.
|
|
|
|
if [ -f /home/selfsigned.crt ]; then
|
|
export NODE_EXTRA_CA_CERTS=/home/selfsigned.crt;
|
|
fi
|
|
|
|
# Background worker flag is per-instance. Defaults to enabled (ws0); ws1+
|
|
# overlays set PENPOT_BACKEND_WORKER=false so scheduled and async tasks only
|
|
# run on ws0, keeping notification Pub/Sub bound to a single Valkey. See
|
|
# mem:devenv/core for the rationale.
|
|
__worker_flag=""
|
|
if [[ "${PENPOT_BACKEND_WORKER:-true}" == "true" ]]; then
|
|
__worker_flag="enable-backend-worker"
|
|
fi
|
|
|
|
export PENPOT_MEDIA_PROCESSING_SERVICE_URI=http://localhost:6065
|
|
|
|
export PENPOT_FLAGS="\
|
|
$PENPOT_FLAGS \
|
|
enable-login-with-password \
|
|
enable-login-with-ldap \
|
|
disable-login-with-oidc \
|
|
disable-login-with-google \
|
|
disable-login-with-github \
|
|
disable-login-with-gitlab \
|
|
disable-telemetry \
|
|
$__worker_flag \
|
|
enable-backend-asserts \
|
|
disable-feature-fdata-pointer-map \
|
|
enable-feature-fdata-objects-map \
|
|
enable-audit-log \
|
|
enable-transit-readable-response \
|
|
disable-remote-media-processing \
|
|
enable-demo-users \
|
|
enable-user-feedback \
|
|
disable-secure-session-cookies \
|
|
enable-smtp \
|
|
enable-account-lockout \
|
|
enable-prepl-server \
|
|
enable-urepl-server \
|
|
enable-nrepl-server \
|
|
enable-rpc-climit \
|
|
enable-rpc-rlimit \
|
|
enable-quotes \
|
|
enable-soft-rpc-rlimit \
|
|
enable-auto-file-snapshot \
|
|
enable-webhooks \
|
|
enable-access-tokens \
|
|
disable-tiered-file-data-storage \
|
|
enable-file-validation \
|
|
enable-file-schema-validation \
|
|
enable-debug-save-faults \
|
|
enable-redis-cache \
|
|
enable-link-preview \
|
|
enable-subscriptions";
|
|
|
|
# Uncomment for nexus integration testing
|
|
# export PENPOT_FLAGS="$PENPOT_FLAGS enable-audit-log-archive";
|
|
# export PENPOT_AUDIT_LOG_ARCHIVE_URI="http://localhost:6070/api/audit";
|
|
|
|
# Default deletion delay for devenv
|
|
export PENPOT_DELETION_DELAY="24h"
|
|
|
|
# Setup default upload media file size to 100MiB
|
|
export PENPOT_MEDIA_MAX_FILE_SIZE=104857600
|
|
|
|
# Setup default multipart upload size to 300MiB
|
|
export PENPOT_HTTP_SERVER_MAX_MULTIPART_BODY_SIZE=314572800
|
|
|
|
export PENPOT_USER_FEEDBACK_DESTINATION="support@example.com"
|
|
|
|
export PENPOT_ADMIN_CONSOLE_URI=http://localhost:3000/admin-console
|
|
|
|
export JAVA_OPTS="\
|
|
-Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager \
|
|
-Djdk.attach.allowAttachSelf \
|
|
-Dlog4j2.configurationFile=log4j2-devenv.xml \
|
|
-Djdk.tracePinnedThreads=full \
|
|
-XX:+UnlockExperimentalVMOptions \
|
|
-XX:+UseShenandoahGC \
|
|
-XX:+UseCompactObjectHeaders \
|
|
-XX:ShenandoahGCMode=generational \
|
|
-XX:-OmitStackTraceInFastThrow \
|
|
--sun-misc-unsafe-memory-access=allow \
|
|
--enable-preview \
|
|
--enable-native-access=ALL-UNNAMED \
|
|
--add-opens=java.base/java.nio=ALL-UNNAMED";
|
|
|
|
function setup_s3_bucket() {
|
|
if [ "${PENPOT_OBJECTS_STORAGE_BACKEND}" != "s3" ]; then
|
|
return 0
|
|
fi
|
|
|
|
local attempts=0
|
|
local endpoint="${PENPOT_OBJECTS_STORAGE_S3_ENDPOINT}"
|
|
local bucket="${PENPOT_OBJECTS_STORAGE_S3_BUCKET}"
|
|
local region="${PENPOT_OBJECTS_STORAGE_S3_REGION}"
|
|
|
|
until aws s3api head-bucket \
|
|
--endpoint-url "$endpoint" \
|
|
--region "$region" \
|
|
--bucket "$bucket" >/dev/null 2>&1; do
|
|
if aws s3 mb "s3://${bucket}" \
|
|
--endpoint-url "$endpoint" \
|
|
--region "$region" >/dev/null 2>&1; then
|
|
return 0
|
|
fi
|
|
|
|
attempts=$((attempts + 1))
|
|
if [ "$attempts" -ge 30 ]; then
|
|
echo "setup_s3_bucket: unable to create s3://${bucket} after ${attempts} attempts" >&2
|
|
return 1
|
|
fi
|
|
sleep 1
|
|
done
|
|
}
|