Fix getUser binding loops & coro race conditions

This commit is contained in:
miruka 2019-07-07 01:37:13 -04:00
parent 683ee3e1cf
commit be152c3acf
7 changed files with 30 additions and 27 deletions

View File

@ -25,7 +25,6 @@ OLD
- Bug fixes - Bug fixes
- Past events loading (limit 100) freezes the GUI - need to move upsert func - Past events loading (limit 100) freezes the GUI - need to move upsert func
to a WorkerScript to a WorkerScript
- Past events loading: text binding loop on name request
- `MessageDelegate.qml:63: TypeError: 'reloadPreviousItem' not a function` - `MessageDelegate.qml:63: TypeError: 'reloadPreviousItem' not a function`
- UI - UI

View File

@ -37,32 +37,31 @@ class App:
return asyncio.run_coroutine_threadsafe(coro, self.loop) return asyncio.run_coroutine_threadsafe(coro, self.loop)
def _call_coro(self, coro: Coroutine) -> str: def _call_coro(self, coro: Coroutine, uuid: str) -> None:
uuid = str(uuid4())
self.run_in_loop(coro).add_done_callback( self.run_in_loop(coro).add_done_callback(
lambda future: CoroutineDone(uuid=uuid, result=future.result()) lambda future: CoroutineDone(uuid=uuid, result=future.result())
) )
return uuid
def call_backend_coro(self, def call_backend_coro(self,
name: str, name: str,
uuid: str,
args: Optional[List[str]] = None, args: Optional[List[str]] = None,
kwargs: Optional[Dict[str, Any]] = None) -> str: kwargs: Optional[Dict[str, Any]] = None) -> None:
return self._call_coro( self._call_coro(
getattr(self.backend, name)(*args or [], **kwargs or {}) getattr(self.backend, name)(*args or [], **kwargs or {}), uuid
) )
def call_client_coro(self, def call_client_coro(self,
account_id: str, account_id: str,
name: str, name: str,
uuid: str,
args: Optional[List[str]] = None, args: Optional[List[str]] = None,
kwargs: Optional[Dict[str, Any]] = None) -> str: kwargs: Optional[Dict[str, Any]] = None) -> None:
client = self.backend.clients[account_id] client = self.backend.clients[account_id]
return self._call_coro( self._call_coro(
getattr(client, name)(*args or [], **kwargs or {}) getattr(client, name)(*args or [], **kwargs or {}), uuid
) )

View File

@ -24,6 +24,8 @@ class Backend:
self.past_tokens: Dict[str, str] = {} # {room_id: token} self.past_tokens: Dict[str, str] = {} # {room_id: token}
self.fully_loaded_rooms: Set[str] = set() # {room_id} self.fully_loaded_rooms: Set[str] = set() # {room_id}
self.pending_profile_requests: Set[str] = set()
def __repr__(self) -> str: def __repr__(self) -> str:
return f"{type(self).__name__}(clients={self.clients!r})" return f"{type(self).__name__}(clients={self.clients!r})"

View File

@ -110,6 +110,10 @@ class MatrixClient(nio.AsyncClient):
async def request_user_update_event(self, user_id: str) -> None: async def request_user_update_event(self, user_id: str) -> None:
if user_id in self.backend.pending_profile_requests:
return
self.backend.pending_profile_requests.add(user_id)
print("Requesting user profile:", user_id) print("Requesting user profile:", user_id)
response = await self.get_profile(user_id) response = await self.get_profile(user_id)
@ -123,6 +127,8 @@ class MatrixClient(nio.AsyncClient):
status_message = "", # TODO status_message = "", # TODO
) )
self.backend.pending_profile_requests.discard(user_id)
@property @property
def all_rooms(self) -> Dict[str, MatrixRoom]: def all_rooms(self) -> Dict[str, MatrixRoom]:

View File

@ -7,15 +7,13 @@ HListModel {
var found = getWhere({"userId": user_id}, 1) var found = getWhere({"userId": user_id}, 1)
if (found.length > 0) { return found[0] } if (found.length > 0) { return found[0] }
append({ py.callCoro("request_user_update_event", [user_id])
return {
"userId": user_id, "userId": user_id,
"displayName": "", "displayName": "",
"avatarUrl": "", "avatarUrl": "",
"statusMessage": "" "statusMessage": ""
}) }
py.callCoro("request_user_update_event", [user_id])
return getWhere({"userId": user_id}, 1)[0]
} }
} }

View File

@ -17,17 +17,17 @@ Python {
} }
function callCoro(name, args, kwargs, callback) { function callCoro(name, args, kwargs, callback) {
call("APP.call_backend_coro", [name, args, kwargs], function(uuid){ var uuid = Math.random() + "." + name
pendingCoroutines[uuid] = callback || function() {} pendingCoroutines[uuid] = callback || function() {}
}) call("APP.call_backend_coro", [name, uuid, args, kwargs])
} }
function callClientCoro(account_id, name, args, kwargs, callback) { function callClientCoro(account_id, name, args, kwargs, callback) {
var args = [account_id, name, args, kwargs] var uuid = Math.random() + "." + name
call("APP.call_client_coro", args, function(uuid){
pendingCoroutines[uuid] = callback || function() {} pendingCoroutines[uuid] = callback || function() {}
}) call("APP.call_client_coro", [account_id, name, uuid, args, kwargs])
} }
Component.onCompleted: { Component.onCompleted: {

View File

@ -6,9 +6,7 @@ Column {
id: accountDelegate id: accountDelegate
width: parent.width width: parent.width
// Avoid binding loop by using Component.onCompleted property var userInfo: users.getUser(model.userId)
property var userInfo: null
Component.onCompleted: userInfo = users.getUser(model.userId)
property bool expanded: true property bool expanded: true
@ -19,6 +17,7 @@ Column {
HUserAvatar { HUserAvatar {
id: avatar id: avatar
// Need to do this because conflict with the model property
Component.onCompleted: userId = model.userId Component.onCompleted: userId = model.userId
} }