refactor progress
This commit is contained in:
@@ -10,17 +10,17 @@ echo "Waiting for Cassandra to start..."
|
||||
sleep 30
|
||||
|
||||
# 2. Extract backup and apply schema
|
||||
docker exec cass bash -c 'apt-get update -qq && apt-get install -y -qq age'
|
||||
docker exec cass sh -c 'apt-get update -qq && apt-get install -y -qq age'
|
||||
docker cp ~/Downloads/backup.tar.age cass:/tmp/
|
||||
docker cp ~/Downloads/key.txt cass:/tmp/
|
||||
docker exec cass bash -c 'age -d -i /tmp/key.txt /tmp/backup.tar.age | tar -C /tmp -xf -'
|
||||
docker exec cass bash -c 'sed "/^WARNING:/d" /tmp/cassandra-backup-*/schema.cql | cqlsh'
|
||||
docker exec cass sh -c 'age -d -i /tmp/key.txt /tmp/backup.tar.age | tar -C /tmp -xf -'
|
||||
docker exec cass sh -c 'sed "/^WARNING:/d" /tmp/cassandra-backup-*/schema.cql | cqlsh'
|
||||
|
||||
# 3. Copy backup to volume and stop Cassandra
|
||||
docker exec cass bash -c 'cp -r /tmp/cassandra-backup-* /var/lib/cassandra/'
|
||||
docker exec cass sh -c 'cp -r /tmp/cassandra-backup-* /var/lib/cassandra/'
|
||||
docker stop cass
|
||||
docker run -d --name cass-util -v cassandra_data:/var/lib/cassandra --entrypoint sleep cassandra:5.0 infinity
|
||||
docker exec cass-util bash -c '
|
||||
docker exec cass-util sh -c '
|
||||
BACKUP_DIR=$(ls -d /var/lib/cassandra/cassandra-backup-* | head -1)
|
||||
DATA_DIR=/var/lib/cassandra/data
|
||||
for keyspace_dir in "$BACKUP_DIR"/*/; do
|
||||
@@ -46,7 +46,7 @@ docker start cass
|
||||
sleep 30
|
||||
|
||||
# 5. Run nodetool refresh on all tables
|
||||
docker exec cass bash -c '
|
||||
docker exec cass sh -c '
|
||||
BACKUP_DIR=$(ls -d /var/lib/cassandra/cassandra-backup-* | head -1)
|
||||
for keyspace_dir in "$BACKUP_DIR"/*/; do
|
||||
keyspace=$(basename "$keyspace_dir")
|
||||
@@ -89,16 +89,16 @@ docker cp "/tmp/${BACKUP_NAME}" ${CASSANDRA_CONTAINER}:/tmp/
|
||||
docker cp /etc/cassandra/age_private_key.txt ${CASSANDRA_CONTAINER}:/tmp/key.txt
|
||||
|
||||
# 3. Stop Cassandra and prepare
|
||||
docker exec ${CASSANDRA_CONTAINER} bash -c 'apt-get update -qq && apt-get install -y -qq age'
|
||||
docker exec ${CASSANDRA_CONTAINER} sh -c 'apt-get update -qq && apt-get install -y -qq age'
|
||||
docker stop ${CASSANDRA_CONTAINER}
|
||||
|
||||
# 4. Extract backup in utility container
|
||||
docker run -d --name cass-restore-util --volumes-from ${CASSANDRA_CONTAINER} --entrypoint sleep cassandra:5.0 infinity
|
||||
docker exec cass-restore-util bash -c 'age -d -i /tmp/key.txt /tmp/${BACKUP_NAME} | tar -C /tmp -xf -'
|
||||
docker exec cass-restore-util bash -c 'cp -r /tmp/cassandra-backup-* /var/lib/cassandra/'
|
||||
docker exec cass-restore-util sh -c 'age -d -i /tmp/key.txt /tmp/${BACKUP_NAME} | tar -C /tmp -xf -'
|
||||
docker exec cass-restore-util sh -c 'cp -r /tmp/cassandra-backup-* /var/lib/cassandra/'
|
||||
|
||||
# 5. Copy SSTable files to existing schema directories
|
||||
docker exec cass-restore-util bash -c '
|
||||
docker exec cass-restore-util sh -c '
|
||||
BACKUP_DIR=$(ls -d /var/lib/cassandra/cassandra-backup-* | head -1)
|
||||
DATA_DIR=/var/lib/cassandra/data
|
||||
for keyspace_dir in "$BACKUP_DIR"/*/; do
|
||||
@@ -124,7 +124,7 @@ docker start ${CASSANDRA_CONTAINER}
|
||||
sleep 30
|
||||
|
||||
# 7. Run nodetool refresh
|
||||
docker exec ${CASSANDRA_CONTAINER} bash -c '
|
||||
docker exec ${CASSANDRA_CONTAINER} sh -c '
|
||||
BACKUP_DIR=$(ls -d /var/lib/cassandra/cassandra-backup-* | head -1)
|
||||
for keyspace_dir in "$BACKUP_DIR"/*/; do
|
||||
keyspace=$(basename "$keyspace_dir")
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/bash
|
||||
#!/usr/bin/env sh
|
||||
|
||||
# Copyright (C) 2026 Fluxer Contributors
|
||||
#
|
||||
@@ -17,7 +17,7 @@
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with Fluxer. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
set -euo pipefail
|
||||
set -eu
|
||||
|
||||
TIMESTAMP=$(date +%Y%m%d-%H%M%S)
|
||||
BACKUP_NAME="cassandra-backup-${TIMESTAMP}"
|
||||
@@ -50,9 +50,9 @@ echo "[$(date)] Collecting snapshot files"
|
||||
mkdir -p "${TEMP_DIR}"
|
||||
|
||||
# Find all snapshot directories and copy to temp location
|
||||
find "${DATA_DIR}" -type d -name "${SNAPSHOT_TAG}" | while read snapshot_dir; do
|
||||
find "${DATA_DIR}" -type d -name "${SNAPSHOT_TAG}" | while IFS= read -r snapshot_dir; do
|
||||
# Get relative path from data dir
|
||||
rel_path=$(dirname $(echo "${snapshot_dir}" | sed "s|${DATA_DIR}/||"))
|
||||
rel_path=$(dirname "${snapshot_dir#$DATA_DIR/}")
|
||||
target_dir="${TEMP_DIR}/${rel_path}"
|
||||
mkdir -p "${target_dir}"
|
||||
cp -r "${snapshot_dir}" "${target_dir}/"
|
||||
@@ -89,7 +89,7 @@ fi
|
||||
# Step 4: Create tar archive and encrypt with age (streaming)
|
||||
echo "[$(date)] Encrypting backup with age..."
|
||||
if ! tar -C /tmp -cf - "${BACKUP_NAME}" | \
|
||||
age -r "$(cat ${AGE_PUBLIC_KEY_FILE})" -o "/tmp/${ENCRYPTED_BACKUP}"; then
|
||||
age -r "$(cat "${AGE_PUBLIC_KEY_FILE}")" -o "/tmp/${ENCRYPTED_BACKUP}"; then
|
||||
echo "[$(date)] Error: Encryption failed"
|
||||
rm -rf "${TEMP_DIR}"
|
||||
nodetool -h "${CASSANDRA_HOST}" clearsnapshot -t "${SNAPSHOT_TAG}"
|
||||
@@ -130,11 +130,11 @@ aws s3 ls "s3://${B2_BUCKET_NAME}/" --endpoint-url="${B2_ENDPOINT_URL}" | \
|
||||
awk '{print $4}' | \
|
||||
sort -r | \
|
||||
tail -n +$((MAX_BACKUP_COUNT + 1)) | \
|
||||
while read -r old_backup; do
|
||||
while IFS= read -r old_backup; do
|
||||
echo "[$(date)] Deleting old backup: ${old_backup}"
|
||||
aws s3 rm "s3://${B2_BUCKET_NAME}/${old_backup}" --endpoint-url="${B2_ENDPOINT_URL}" || true
|
||||
done
|
||||
|
||||
echo "[$(date)] Backup process completed successfully"
|
||||
echo "[$(date)] Backup name: ${ENCRYPTED_BACKUP}"
|
||||
echo "[$(date)] Backup size: ${BACKUP_SIZE}"
|
||||
echo "[$(date)] Backup size: ${BACKUP_SIZE}"
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
ALTER TABLE fluxer.users ADD traits set<text>;
|
||||
@@ -0,0 +1,2 @@
|
||||
ALTER TABLE fluxer.user_settings ADD bot_default_guilds_restricted boolean;
|
||||
ALTER TABLE fluxer.user_settings ADD bot_restricted_guilds set<bigint>;
|
||||
@@ -0,0 +1,20 @@
|
||||
CREATE TABLE IF NOT EXISTS fluxer.system_dm_jobs (
|
||||
job_type text,
|
||||
job_id bigint,
|
||||
admin_user_id bigint,
|
||||
status text,
|
||||
content text,
|
||||
registration_start timestamp,
|
||||
registration_end timestamp,
|
||||
excluded_guild_ids set<text>,
|
||||
target_count int,
|
||||
sent_count int,
|
||||
failed_count int,
|
||||
last_error text,
|
||||
worker_job_key text,
|
||||
created_at timestamp,
|
||||
updated_at timestamp,
|
||||
approved_by bigint,
|
||||
approved_at timestamp,
|
||||
PRIMARY KEY ((job_type), job_id)
|
||||
) WITH CLUSTERING ORDER BY (job_id DESC);
|
||||
@@ -0,0 +1,22 @@
|
||||
CREATE TABLE IF NOT EXISTS fluxer.admin_api_keys (
|
||||
key_id bigint,
|
||||
key_hash text,
|
||||
name text,
|
||||
created_by_user_id bigint,
|
||||
created_at timestamp,
|
||||
last_used_at timestamp,
|
||||
expires_at timestamp,
|
||||
version int,
|
||||
PRIMARY KEY (key_id)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS fluxer.admin_api_keys_by_creator (
|
||||
created_by_user_id bigint,
|
||||
key_id bigint,
|
||||
created_at timestamp,
|
||||
name text,
|
||||
expires_at timestamp,
|
||||
last_used_at timestamp,
|
||||
version int,
|
||||
PRIMARY KEY (created_by_user_id, key_id)
|
||||
) WITH CLUSTERING ORDER BY (key_id DESC);
|
||||
@@ -0,0 +1,2 @@
|
||||
ALTER TABLE fluxer.admin_api_keys ADD acls set<text>;
|
||||
ALTER TABLE fluxer.admin_api_keys_by_creator ADD acls set<text>;
|
||||
@@ -0,0 +1,9 @@
|
||||
CREATE TABLE IF NOT EXISTS fluxer.relationships_by_target (
|
||||
target_user_id bigint,
|
||||
source_user_id bigint,
|
||||
type int,
|
||||
nickname text,
|
||||
since timestamp,
|
||||
version int,
|
||||
PRIMARY KEY (target_user_id, source_user_id, type)
|
||||
) WITH CLUSTERING ORDER BY (source_user_id ASC, type ASC);
|
||||
@@ -0,0 +1,6 @@
|
||||
CREATE TABLE IF NOT EXISTS fluxer.messages_by_author_id_v2 (
|
||||
author_id bigint,
|
||||
message_id bigint,
|
||||
channel_id bigint,
|
||||
PRIMARY KEY ((author_id), message_id)
|
||||
) WITH CLUSTERING ORDER BY (message_id DESC);
|
||||
@@ -0,0 +1,28 @@
|
||||
CREATE TABLE IF NOT EXISTS fluxer.csam_evidence_packages (
|
||||
report_id bigint PRIMARY KEY,
|
||||
resource_type text,
|
||||
bucket text,
|
||||
key text,
|
||||
cdn_url text,
|
||||
filename text,
|
||||
content_type text,
|
||||
channel_id bigint,
|
||||
message_id bigint,
|
||||
guild_id bigint,
|
||||
user_id bigint,
|
||||
match_tracking_id text,
|
||||
match_details text,
|
||||
frames text,
|
||||
hashes text,
|
||||
context_snapshot text,
|
||||
created_at timestamp,
|
||||
expires_at timestamp,
|
||||
integrity_sha256 text,
|
||||
evidence_zip_key text
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS fluxer.csam_evidence_legal_holds (
|
||||
report_id bigint PRIMARY KEY,
|
||||
held_until timestamp,
|
||||
created_at timestamp
|
||||
);
|
||||
@@ -0,0 +1,21 @@
|
||||
CREATE TABLE IF NOT EXISTS fluxer.csam_scan_jobs (
|
||||
job_id text PRIMARY KEY,
|
||||
resource_type text,
|
||||
bucket text,
|
||||
key text,
|
||||
cdn_url text,
|
||||
filename text,
|
||||
content_type text,
|
||||
channel_id bigint,
|
||||
message_id bigint,
|
||||
guild_id bigint,
|
||||
user_id bigint,
|
||||
status text,
|
||||
enqueue_time timestamp,
|
||||
last_updated timestamp,
|
||||
match_tracking_id text,
|
||||
match_details text,
|
||||
hashes text,
|
||||
error_message text,
|
||||
expires_at timestamp
|
||||
);
|
||||
@@ -0,0 +1,6 @@
|
||||
CREATE TABLE IF NOT EXISTS fluxer.csam_evidence_expirations (
|
||||
bucket text,
|
||||
expires_at timestamp,
|
||||
report_id bigint,
|
||||
PRIMARY KEY ((bucket), expires_at, report_id)
|
||||
) WITH CLUSTERING ORDER BY (expires_at ASC);
|
||||
@@ -0,0 +1,2 @@
|
||||
ALTER TABLE fluxer.guild_stickers ADD animated boolean;
|
||||
ALTER TABLE fluxer.guild_stickers_by_sticker_id ADD animated boolean;
|
||||
@@ -0,0 +1 @@
|
||||
ALTER TYPE fluxer.message_sticker_item ADD animated boolean;
|
||||
@@ -0,0 +1,10 @@
|
||||
CREATE TABLE IF NOT EXISTS fluxer.ncmec_submissions (
|
||||
report_id bigint PRIMARY KEY,
|
||||
status text,
|
||||
ncmec_report_id text,
|
||||
submitted_at timestamp,
|
||||
submitted_by_admin_id bigint,
|
||||
failure_reason text,
|
||||
created_at timestamp,
|
||||
updated_at timestamp
|
||||
);
|
||||
@@ -0,0 +1,2 @@
|
||||
ALTER TYPE fluxer.message_attachment ADD duration_secs int;
|
||||
ALTER TYPE fluxer.message_attachment ADD waveform text;
|
||||
@@ -0,0 +1 @@
|
||||
ALTER TABLE fluxer.favorite_memes ADD klipy_slug text;
|
||||
@@ -0,0 +1 @@
|
||||
ALTER TABLE fluxer.user_settings ADD trusted_domains set<text>;
|
||||
@@ -0,0 +1 @@
|
||||
ALTER TABLE fluxer.user_settings ADD default_hide_muted_channels boolean;
|
||||
@@ -0,0 +1,2 @@
|
||||
ALTER TYPE fluxer.guild_folder ADD flags int;
|
||||
ALTER TYPE fluxer.guild_folder ADD icon text;
|
||||
@@ -0,0 +1,17 @@
|
||||
CREATE TYPE IF NOT EXISTS fluxer.message_embed_child (
|
||||
type text,
|
||||
title text,
|
||||
description text,
|
||||
url text,
|
||||
timestamp timestamp,
|
||||
color int,
|
||||
author frozen<message_embed_author>,
|
||||
provider frozen<message_embed_provider>,
|
||||
thumbnail frozen<message_embed_media>,
|
||||
image frozen<message_embed_media>,
|
||||
video frozen<message_embed_media>,
|
||||
footer frozen<message_embed_footer>,
|
||||
fields frozen<list<message_embed_field>>,
|
||||
nsfw boolean
|
||||
);
|
||||
ALTER TYPE fluxer.message_embed ADD children frozen<list<message_embed_child>>;
|
||||
@@ -0,0 +1 @@
|
||||
ALTER TABLE fluxer.guilds ADD message_history_cutoff timestamp;
|
||||
@@ -0,0 +1 @@
|
||||
ALTER TABLE fluxer.guilds ADD members_indexed_at timestamp;
|
||||
@@ -0,0 +1,16 @@
|
||||
CREATE TABLE IF NOT EXISTS fluxer.user_connections (
|
||||
user_id bigint,
|
||||
connection_type text,
|
||||
connection_id text,
|
||||
identifier text,
|
||||
name text,
|
||||
verified boolean,
|
||||
visibility_flags int,
|
||||
sort_order int,
|
||||
verification_token text,
|
||||
verified_at timestamp,
|
||||
last_verified_at timestamp,
|
||||
created_at timestamp,
|
||||
version int,
|
||||
PRIMARY KEY ((user_id), connection_type, connection_id)
|
||||
) WITH CLUSTERING ORDER BY (connection_type ASC, connection_id DESC);
|
||||
@@ -0,0 +1,46 @@
|
||||
CREATE TABLE IF NOT EXISTS fluxer.donors (
|
||||
email text,
|
||||
stripe_customer_id text,
|
||||
|
||||
business_name text,
|
||||
tax_id text,
|
||||
tax_id_type text,
|
||||
|
||||
stripe_subscription_id text,
|
||||
subscription_amount_cents int,
|
||||
subscription_currency text,
|
||||
subscription_interval text,
|
||||
subscription_current_period_end timestamp,
|
||||
subscription_cancel_at timestamp,
|
||||
|
||||
created_at timestamp,
|
||||
updated_at timestamp,
|
||||
version int,
|
||||
PRIMARY KEY ((email))
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS fluxer.donors_by_stripe_customer_id (
|
||||
stripe_customer_id text,
|
||||
email text,
|
||||
PRIMARY KEY ((stripe_customer_id), email)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS fluxer.donors_by_stripe_subscription_id (
|
||||
stripe_subscription_id text,
|
||||
email text,
|
||||
PRIMARY KEY ((stripe_subscription_id), email)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS fluxer.donor_magic_link_tokens (
|
||||
token_ text,
|
||||
donor_email text,
|
||||
expires_at timestamp,
|
||||
used_at timestamp,
|
||||
PRIMARY KEY ((token_))
|
||||
) WITH default_time_to_live = 900;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS fluxer.donor_magic_link_tokens_by_email (
|
||||
donor_email text,
|
||||
token_ text,
|
||||
PRIMARY KEY ((donor_email), token_)
|
||||
) WITH default_time_to_live = 900;
|
||||
@@ -0,0 +1,12 @@
|
||||
CREATE TABLE IF NOT EXISTS fluxer.password_change_tickets (
|
||||
ticket text PRIMARY KEY,
|
||||
user_id bigint,
|
||||
code text,
|
||||
code_sent_at timestamp,
|
||||
code_expires_at timestamp,
|
||||
verified boolean,
|
||||
verification_proof text,
|
||||
status text,
|
||||
created_at timestamp,
|
||||
updated_at timestamp
|
||||
);
|
||||
@@ -0,0 +1 @@
|
||||
ALTER TABLE fluxer.applications ADD bot_require_code_grant boolean;
|
||||
@@ -0,0 +1,21 @@
|
||||
CREATE TABLE IF NOT EXISTS fluxer.guild_discovery (
|
||||
guild_id bigint,
|
||||
status text,
|
||||
category_id int,
|
||||
description text,
|
||||
applied_at timestamp,
|
||||
reviewed_at timestamp,
|
||||
reviewed_by bigint,
|
||||
review_reason text,
|
||||
removed_at timestamp,
|
||||
removed_by bigint,
|
||||
removal_reason text,
|
||||
PRIMARY KEY ((guild_id))
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS fluxer.guild_discovery_by_status (
|
||||
status text,
|
||||
applied_at timestamp,
|
||||
guild_id bigint,
|
||||
PRIMARY KEY ((status), applied_at, guild_id)
|
||||
) WITH CLUSTERING ORDER BY (applied_at DESC, guild_id DESC);
|
||||
Reference in New Issue
Block a user