On Fri, Aug 12, 2022 at 09:02:01AM +0200, Bence Ferdinandy wrote:
- If I receive an email at t=0 and start mbsync and then receive emails
while mbsync is still running I'm guessing those emails may or may not be
synced depending on when exactly they arrived, but no guarantees, right?

correct, as documented under "inherent problems" in the manual.

- Would mbsync be confused if multiple instances were triggered in
parallel?

no, as documented in "description" in the manual. but it won't quite do what you want, either:

Basically what I'm thinking about is that if parallel running is not a
problem, than the best and easiest would just to trigger on all incoming
mail so I get it as fast as possible

that won't guarantee that you actually get the mails in a timely manner, as the subsequent instances will just exit immediately.

Or are there any best practices for this?

i'm using the attached script, which does box-specific event compression and allows invoking a post-sync action (i use box-specific audio signals).
#! /bin/bash
# -x
#exec </dev/null >>$(me).log 2>&1;echo;date

MBSYNC=/usr/local/bin/mbsync

# pattern throttle maxthrottle sleep
mailclasses="
inbox 3 10 0
*-null 60 180 300
* 20 120 240
"
maxfetchtime=320

maildir=$HOME/maildir
channel=home

getpid()
{
  # bash bug: $$ won't be updated in a forked process [()&]
  bash -c 'echo $PPID'
}

mysleep()
{
  sleep $1 & pid=$!
  trap 'kill $pid; exit' 15
  wait $pid
  trap - 15
}

getlock()
{
  if ! lockfile -s 0 -r 0 -l $maxfetchtime ${lf[$1]}.lock 2>/dev/null
  then
    if test $force; then
      pid=$(cat ${lf[$1]}.pid 2>/dev/null)
      test -z "$pid" -o "$pid" = 0 && return 1
      kill $pid
      rm ${lf[$1]}.pid
    else
      return 1
    fi
  fi
}

freelock()
{
  force=
  cont=$((${delay2[i]}+$now-$(date '+%s')))
  if ((cont > 0)); then
    getpid > ${lf[i]}.pid
    mysleep $cont ${lf[i]}.pid
    rm ${lf[$i]}.pid
  fi
  rm -f ${lf[i]}.lock
  test -f ${lf[i]}.need # must be last!
}

throttle()
{
  if test -z "$force" -a ${delay1[$1]} != 0; then
    getpid > ${lf[$1]}.pid
    expire=$(($now+${maxdelay[$1]}))
    while :; do
      test $(date -r ${lf[$1]}.need '+%s') -lt $(($now-${delay1[$1]})) && break
      test $now -lt $expire || break
      mysleep ${delay1[$1]}
      touch ${lf[$1]}.lock
      now=$(date '+%s')
    done
    rm ${lf[$1]}.pid
    mysleep 1
  fi
}

getonly=
force=
bgnd=
info=
unset boxes

while test "$1"; do
  case $1 in
    -f) force=1; shift;;
    -g) getonly=--pull; shift;;
    -b) bgnd=1; shift;;
    -i) info=$2; shift 2;;
    -a) IFS=$'\n'; boxes=($($MBSYNC -ql $channel)); IFS=$' \t\n'; shift;;
    -*) echo "unknown option '$1'"; exit 1;;
    *) break;;
  esac
done
test -z "$1" && set -- "${boxes[@]}"
test -z "$1" && echo "no mailbox specified" && exit 1

n=0
while test -n "$1"; do
  mbox[n]=$channel:$1
  lf[n]=~/tmp/getmail/$1
  mbe[n]=$maildir/$1/isyncerror
  eval `echo "${mailclasses:1:$((${#mailclasses}-2))}" |
  while read pat tdelay1 tmaxdelay tdelay2; do
    case $1 in
      $pat)
        echo "delay1[n]=$tdelay1 maxdelay[n]=$tmaxdelay delay2[n]=$tdelay2"
        break
        ;;
    esac
  done`
  shift
  echo "$info" >> ${lf[n]}.need
  test -n "$getonly" || touch ${lf[n]}.need.full
  getlock $n || continue
  ((n++))
done
test $n = 0 && exit

now=$(date '+%s')
if test -z "$bgnd"; then
  for i in "${lf[@]}"; do
    mv $i.need $i.doing
    test -z "$getonly" && rm -f $i.need.full
  done
  $MBSYNC -C $getonly "${mbox[@]}"
  for i in "${lf[@]}"; do
    . $i.doing
    rm $i.doing
  done
fi
for ((i=0; i<n; i++)); do
  (
    test -n "$bgnd" || { freelock && getlock $i; } || exit
    while :; do
      if test -f ${mbe[i]}; then
        freelock
        exit
      fi
      now=$(date '+%s')
      throttle $i
      mv ${lf[i]}.need ${lf[i]}.doing
      if test -f ${lf[i]}.need.full; then
        rm ${lf[i]}.need.full
        getonly=
      else
        getonly=--pull
      fi
      if ! log=$($MBSYNC -Cq $getonly ${mbox[i]} 2>&1); then
        if ! echo "$log" | egrep -q -i "(unexpected tag|unexpected 
EOF|Unexpected token |Broken pipe|Temporary failure|timeout\\.|Connection 
refused|Connection reset by peer|Connection timed out|Unidentified socket 
error|duplicate UID|channel .* is locked\$)"; then
          echo "$log" > ${mbe[i]}
          echo "$log" | mail -s "getmail failed for '${mbox[i]}'" $(id -nu)
        fi
        cat ${lf[i]}.doing >> ${lf[i]}.need
        rm ${lf[i]}.doing
        test -z "$getonly" && touch ${lf[i]}.need.full
        freelock
        exit
      fi
      . ${lf[i]}.doing
      rm ${lf[i]}.doing
      freelock || exit
      getlock $i || exit
    done
  ) &
done
_______________________________________________
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel

Reply via email to