Refactor to use concurrent.futures (via backported futures library) and its ThreadPoolExecutor for resolving promises