Skip to content

Commit

Permalink
Make sessions threadsafe
Browse files Browse the repository at this point in the history
I ran into the thread safety issue described here:

#153

According to boto3's docs, each thread should have its own session instance:

http://boto3.readthedocs.io/en/latest/guide/resources.html#multithreading

I resolved this by modifying the session property on the connection
class. It makes self._session into a thread local variable, and
attaches a session to self._session.session. The session property still
has the same behavior, but now it's creating a session on a
per-connection-per-thread basis instead of just on a per-thread basis.

This issue was intermittent to begin with, and I hadn't figured out a
way to reliably reproduce it, or I would have written a test. It still
passes PynamoDB's unit tests, and I haven't run into the thread safety
issue described in #153 since I've been running the patched version.
  • Loading branch information
AusIV committed Feb 21, 2017
1 parent e5858ef commit dc7332b
Showing 1 changed file with 5 additions and 4 deletions.
9 changes: 5 additions & 4 deletions pynamodb/connection/base.py
Expand Up @@ -7,6 +7,7 @@
import math
import random
import time
from threading import local

import six
from six.moves import range
Expand Down Expand Up @@ -181,7 +182,7 @@ def __init__(self, region=None, host=None, session_cls=None,
request_timeout_seconds=None, max_retry_attempts=None, base_backoff_ms=None):
self._tables = {}
self.host = host
self._session = None
self._session = local()
self._requests_session = None
self._client = None
if region:
Expand Down Expand Up @@ -392,9 +393,9 @@ def session(self):
"""
Returns a valid botocore session
"""
if self._session is None:
self._session = get_session()
return self._session
if getattr(self._session, "session", None) is None:
self._session.session = get_session()
return self._session.session

@property
def requests_session(self):
Expand Down

0 comments on commit dc7332b

Please sign in to comment.