#!/usr/bin/env bash

set -e
set +x

PATH=/usr/local/bin:$PATH
NEO4J_HOME=${NEO4J_HOME:-'/var/lib/neo4j'}
NEO4J_HEAP_SIZE=${NEO4J_HEAP_SIZE:-'30G'}
NEO4J_PAGECACHE=${NEO4J_PAGECACHE:-'32G'}
NEO4J_DEBUG_LOGFILE=${NEO4J_DEBUG_LOGFILE:-'/var/log/neo4j/debug.log'}
S3_BACKUP_OBJECT_PATH=${S3_BACKUP_OBJECT_PATH:-'prod-orcdbucket/backup/neo4j/prod-neo4j-cluster.theorchard.io'}
S3_BACKUP_OBJECT_NAME=${S3_BACKUP_OBJECT_NAME:-'neo4j-cluster-backup.tar.gz'}
S3_4X_BACKUP_OBJECT_NAME=${S3_4X_BACKUP_OBJECT_NAME:-'neo4j-cluster-4x-backup.tar.gz'}
S3_4X_BACKUP_KMS_KEY=${S3_4X_BACKUP_KMS_KEY:-'839dc350-52d3-4bd0-b37f-da708ba77aca'}
SCRIPT_LOGFILE=${SCRIPT_LOGFILE:-'/var/log/neo4j/upgrader.log'}
UPGRADE_TIMEOUT=${UPGRADE_TIMEOUT:-14400}

# We are making the calculated assessment that this won't have to be used for long, or else we'd extend the Python tools and get better visibility. Hope we're right.

log() {
  printf '[%s] [%s] %s\n' "${0##*/}" "$( date '+%Y-%m-%dT%H:%M:%S' )" "${@}" >> "${SCRIPT_LOGFILE}"
}


# Clean start tasks
log 'Running clean start tasks'
mkdir -m 775 -p "${NEO4J_HOME}/backup" && chgrp -R neo4j "${NEO4J_HOME}/backup"
for pid in $(pgrep java); do 
  kill -9 "${pid}" && systemctl stop neo4j
done
rm -rf "${NEO4J_HOME}/data/databases/graph.db" "${NEO4J_HOME}/data/databases/neo4j" "${NEO4J_HOME}/data/transactions/neo4j"
rm -rf "${NEO4J_DEBUG_LOGFILE}"
rm -rf "${NEO4J_HOME}/backup/*"

# Pull down existing backup
log 'Pulling down initial backup from S3'
aws s3 cp "s3://${S3_BACKUP_OBJECT_PATH}/${S3_BACKUP_OBJECT_NAME}" "${NEO4J_HOME}/backup/${S3_BACKUP_OBJECT_NAME}"

# Extract 3.5 backup
log 'Extracting backup archive'
tar -zxvf "${NEO4J_HOME}/backup/${S3_BACKUP_OBJECT_NAME}" -C "${NEO4J_HOME}/backup/"

# Move 3.5 backup into place
mv -f "${NEO4J_HOME}/backup/neo4j-cluster-backup" "${NEO4J_HOME}/data/databases/graph.db"

chown -R neo4j:neo4j "${NEO4J_HOME}/data/databases/graph.db"

# Start neo4j and allow it to upgrade
log 'Restarting Neo4j now that initial database has been seeded'
systemctl start neo4j

# Wait a while for it to upgrade in place
UPGRADE_ENDTIME=$(( $(date +%s) + ${UPGRADE_TIMEOUT} ))

while [ "$(date +%s)" -lt "${UPGRADE_ENDTIME}" ]; do
  if grep -q 'Successfully finished upgrade of database' "${NEO4J_DEBUG_LOGFILE}"; then
    log 'Neo4j ugprade complete. Checking if service is listening...'
    sleep 60
    if [ -n "$(ss -Hl '( sport = :7687 )')" ]; then 
      log 'Neo4j service is listening'
      break
    else
      log 'Neo4j service is not yet listening. Sleeping...'
      sleep 300
    fi
  else 
    log 'Neo4j upgrade success log entry not found. Sleeping...'
    sleep 300
  fi
done

# Make a backup from this newly upgraded database
log 'Taking a backup using neo4j-admin'
HEAP_SIZE=${NEO4J_HEAP_SIZE} neo4j-admin backup \
  --backup-dir="${NEO4J_HOME}/backup/" \
  --from="$(hostname -i):6362" \
  --database=graph.db \
  --pagecache="${NEO4J_PAGECACHE}" \
  --check-consistency=false \
  --prepare-restore=false

# Now create a tarball, since that's what downstream tools expect
log 'Making a tarball of the newly created backup'
tar -zcvf "${NEO4J_HOME}/backup/${S3_4X_BACKUP_OBJECT_NAME}" "${NEO4J_HOME}/backup/graph.db"

# Now upload the new backup to a new location
log 'Attempting to upload upgraded backup tarball to S3'
if aws s3 cp "${NEO4J_HOME}/backup/${S3_4X_BACKUP_OBJECT_NAME}" "s3://${S3_BACKUP_OBJECT_PATH}/${S3_4X_BACKUP_OBJECT_NAME}" --sse aws:kms --sse-kms-key-id "${S3_4X_BACKUP_KMS_KEY}"; then
  log "Uploaded backup to s3://${S3_BACKUP_OBJECT_PATH}/${S3_4X_BACKUP_OBJECT_NAME}"
else
  log "Backup failed: exit code $?"
fi

# Cleanup tasks
log 'Running cleanup tasks'
for pid in $(pgrep java); do 
  kill -9 "${pid}" && systemctl stop neo4j
done
systemctl disable neo4j
rm -rf "${NEO4J_DEBUG_LOGFILE}"
rm -rf "${NEO4J_HOME}/data/databases/graph.db" "${NEO4J_HOME}/data/databases/neo4j" "${NEO4J_HOME}/data/transactions/neo4j"
rm -rf "${NEO4J_HOME}/backup/*"

log 'Finished cleanup tasks. Exiting...'
