Skip to content

Commit

Permalink
soft-pool: lock channel queue when trying to open new channels (#31)
Browse files Browse the repository at this point in the history
  • Loading branch information
pmrowla authored Apr 6, 2023
1 parent b62b9a3 commit c38d954
Showing 1 changed file with 20 additions and 9 deletions.
29 changes: 20 additions & 9 deletions sshfs/pools/soft.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import asyncio
import heapq
from collections import Counter
from contextlib import asynccontextmanager
Expand All @@ -19,20 +20,23 @@ class SFTPSoftChannelPool(BaseSFTPChannelPool):

def __init__(self, *args, **kwargs):
self._channels = Counter()
self._channels_lock = asyncio.Lock()
super().__init__(*args, **kwargs)

@asynccontextmanager
async def get(self):
[(least_used_channel, num_connections)] = (
heapq.nsmallest(1, self._channels.items(), lambda kv: kv[1])
or self._NO_CHANNELS
)

least_used_channel, num_connections = self._least_used()
if least_used_channel is None or num_connections >= self._THRESHOLD:
channel = await self._maybe_new_channel()
if channel is not None:
least_used_channel = channel
num_connections = 0
async with self._channels_lock:
channel = await self._maybe_new_channel()
if channel is not None:
least_used_channel = channel
num_connections = 0
self._channels[least_used_channel] = 0

if channel is None:
# another coroutine may have opened a channel while we waited
least_used_channel, num_connections = self._least_used()

if least_used_channel is None:
raise ValueError("Can't create any SFTP connections!")
Expand All @@ -46,6 +50,13 @@ async def get(self):
async def _cleanup(self):
self._channels.clear()

def _least_used(self):
[(least_used_channel, num_connections)] = (
heapq.nsmallest(1, self._channels.items(), lambda kv: kv[1])
or self._NO_CHANNELS
)
return least_used_channel, num_connections

@property
def active_channels(self):
return len(self._channels)
Expand Down

0 comments on commit c38d954

Please sign in to comment.