The ID discovery script exited about a second after starting. Since the switch to `atMaxRate`, neither the discovery loop nor the request loop was awaited, and `atMaxRate` didn't await its callback, so the script went straight to `save()`, committed and exited while overlapping duplicate requests failed in the background.
- Awaited both `atMaxRate` loops and the callback inside `atMaxRate`
- Moved the ID range exhaustion check out of the retry loop so retries can't remove extra regions
- Treated network and JSON errors as failed API calls so a long run retries instead of crashing without saving
Fixes#306