Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add workaround for a multi thread issue of ruamel.yaml #200

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 29 additions & 7 deletions ansible_risk_insight/yaml.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,15 @@
import io
from contextvars import ContextVar
from ruamel.yaml import YAML
from ruamel.yaml.emitter import EmitterError


_yaml: ContextVar[YAML] = ContextVar("yaml")


def _set_yaml():
if not _yaml.get(None):
yaml = YAML(typ="rt", pure=True)
def _set_yaml(force=False):
if not _yaml.get(None) or force:
yaml = YAML(typ="safe", pure=True)
yaml.default_flow_style = False
yaml.preserve_quotes = True
yaml.allow_duplicate_keys = True
Expand Down Expand Up @@ -53,9 +54,30 @@ def load(stream: any):
return yaml.load(stream)


# `ruamel.yaml` has a bug around multi-threading, and its YAML() instance could be broken
# while concurrent dump() operation. So we try retrying if the specific error occurs.
# Bug details: https://sourceforge.net/p/ruamel-yaml/tickets/367/
def dump(data: any):
_set_yaml()
yaml = _yaml.get()
output = io.StringIO()
yaml.dump(data, output)
return output.getvalue()
retry = 2
err = None
result = None
for i in range(retry):
try:
yaml = _yaml.get()
output = io.StringIO()
yaml.dump(data, output)
result = output.getvalue()
except EmitterError as exc:
err = exc
except Exception:
raise
if err:
if i < retry - 1:
_set_yaml(force=True)
err = None
else:
raise err
else:
break
return result
Loading