Reimplement transmitter thread as future

This avoids the need for an explicit `.join()`, and removes the need for the TransmitterThread wrapper class.
This commit is contained in:
Shane McDonald
2022-02-28 08:28:36 -05:00
parent cb57752903
commit 2df3ca547b

View File

@@ -7,8 +7,6 @@ import logging
import os import os
import shutil import shutil
import socket import socket
import sys
import threading
import time import time
import yaml import yaml
@@ -247,16 +245,6 @@ def worker_cleanup(node_name, vargs, timeout=300.0):
return stdout return stdout
class TransmitterThread(threading.Thread):
def run(self):
self.exc = None
try:
super().run()
except Exception:
self.exc = sys.exc_info()
class AWXReceptorJob: class AWXReceptorJob:
def __init__(self, task, runner_params=None): def __init__(self, task, runner_params=None):
self.task = task self.task = task
@@ -296,17 +284,23 @@ class AWXReceptorJob:
# reading. # reading.
sockin, sockout = socket.socketpair() sockin, sockout = socket.socketpair()
transmitter_thread = TransmitterThread(target=self.transmit, args=[sockin]) with concurrent.futures.ThreadPoolExecutor(max_workers=1) as executor:
transmitter_thread.start() transmitter_future = executor.submit(self.transmit, sockin)
# submit our work, passing
# in the right side of our socketpair for reading.
_kw = {} _kw = {}
if self.work_type == 'ansible-runner': if self.work_type == 'ansible-runner':
_kw['node'] = self.task.instance.execution_node _kw['node'] = self.task.instance.execution_node
use_stream_tls = get_conn_type(_kw['node'], receptor_ctl).name == "STREAMTLS" use_stream_tls = get_conn_type(_kw['node'], receptor_ctl).name == "STREAMTLS"
_kw['tlsclient'] = get_tls_client(use_stream_tls) _kw['tlsclient'] = get_tls_client(use_stream_tls)
result = receptor_ctl.submit_work(worktype=self.work_type, payload=sockout.makefile('rb'), params=self.receptor_params, signwork=self.sign_work, **_kw)
# submit our work, passing in the right side of our socketpair for reading.
result = receptor_ctl.submit_work(
worktype=self.work_type, payload=sockout.makefile('rb'), params=self.receptor_params, signwork=self.sign_work, **_kw
)
sockin.close()
sockout.close()
self.unit_id = result['unitid'] self.unit_id = result['unitid']
# Update the job with the work unit in-memory so that the log_lifecycle # Update the job with the work unit in-memory so that the log_lifecycle
# will print out the work unit that is to be associated with the job in the database # will print out the work unit that is to be associated with the job in the database
@@ -324,13 +318,9 @@ class AWXReceptorJob:
self.task.update_model(self.task.instance.pk, work_unit_id=result['unitid']) self.task.update_model(self.task.instance.pk, work_unit_id=result['unitid'])
self.task.instance.log_lifecycle("work_unit_id_assigned") self.task.instance.log_lifecycle("work_unit_id_assigned")
sockin.close() # Throws an exception if the transmit failed.
sockout.close() # Will be caught by the try/except in BaseTask#run.
transmitter_future.result()
if transmitter_thread.exc:
raise transmitter_thread.exc[1].with_traceback(transmitter_thread.exc[2])
transmitter_thread.join()
# Artifacts are an output, but sometimes they are an input as well # Artifacts are an output, but sometimes they are an input as well
# this is the case with fact cache, where clearing facts deletes a file, and this must be captured # this is the case with fact cache, where clearing facts deletes a file, and this must be captured