1
0
mirror of https://github.com/lutris/lutris synced 2024-07-05 16:38:42 +00:00

Make LibrarySyncer.is_sync a global variable again.

It really needs to be, or it's just useless - resulting in a UI error and potentially multiple threads syncing at once.

The problem is that _IS_LOCAL_LIBRARY_SYNCING is now a mutable global, and in Python this is treacherous. 'from x import G' copies G into scope, which is bad news for a global like this.

 'import x' followed by 'x.G' works, but this is real dark corner, so I've added a global function just to read the global variable; it reads the original, not a copy, even if you copy the function reference into scope with 'from x import f'.

 So this works without making LibrarySyncer a singleton.
This commit is contained in:
Daniel Johnson 2024-04-02 04:43:37 -04:00
parent e2c68e1b41
commit a95ff285dc
2 changed files with 21 additions and 9 deletions

View File

@ -8,7 +8,12 @@ from lutris.gui.config.base_config_box import BaseConfigBox
from lutris.gui.config.updates_box import UpdateButtonBox
from lutris.gui.dialogs import ClientLoginDialog, QuestionDialog
from lutris.util.jobs import AsyncCall
from lutris.util.library_sync import LOCAL_LIBRARY_SYNCED, LOCAL_LIBRARY_SYNCING, LibrarySyncer
from lutris.util.library_sync import (
LOCAL_LIBRARY_SYNCED,
LOCAL_LIBRARY_SYNCING,
LibrarySyncer,
is_local_library_syncing,
)
from lutris.util.steam.config import STEAM_ACCOUNT_SETTING, get_steam_users
from lutris.util.strings import time_ago
@ -55,8 +60,7 @@ class AccountsBox(BaseConfigBox):
def on_realize(self, _widget):
self.library_syncing_source_id = LOCAL_LIBRARY_SYNCING.register(self.on_local_library_syncing)
self.library_synced_source_id = LOCAL_LIBRARY_SYNCED.register(self.on_local_library_synced)
library_syncer = LibrarySyncer()
if library_syncer.is_syncing:
if is_local_library_syncing():
self.on_local_library_syncing()
def on_unrealize(self, _widget):

View File

@ -14,11 +14,18 @@ LIBRARY_URL = settings.SITE_URL + "/api/users/library"
LOCAL_LIBRARY_SYNCING = NotificationSource()
LOCAL_LIBRARY_SYNCED = NotificationSource()
LOCAL_LIBRARY_UPDATED = NotificationSource()
_IS_LOCAL_LIBRARY_SYNCING = False
def is_local_library_syncing():
"""True if the library is syncing now; attempting to sync again will do nothing if so."""
# This provides access to the mutable global _IS_LOCAL_LIBRARY_SYNCING in a safer
# way; if you just import the global directly you get a copy of its current state at import
# time which is not very useful.
return _IS_LOCAL_LIBRARY_SYNCING
class LibrarySyncer:
is_syncing = False
def get_local_library(self, since=None):
game_library = []
pga_games = get_games()
@ -47,9 +54,9 @@ class LibrarySyncer:
return game_library
def sync_local_library(self, force: bool = False) -> None:
global IS_LOCAL_LIBRARY_SYNCING
global _IS_LOCAL_LIBRARY_SYNCING
if self.is_syncing:
if _IS_LOCAL_LIBRARY_SYNCING:
return
if not force and settings.read_setting("last_library_sync_at"):
@ -69,7 +76,8 @@ class LibrarySyncer:
LOCAL_LIBRARY_SYNCING.fire()
any_local_changes = False
try:
self.is_syncing = True
_IS_LOCAL_LIBRARY_SYNCING = True
time.sleep(15)
request = http.Request(
url,
headers={
@ -151,7 +159,7 @@ class LibrarySyncer:
)
settings.write_setting("last_library_sync_at", int(time.time()))
finally:
self.is_syncing = False
_IS_LOCAL_LIBRARY_SYNCING = False
LOCAL_LIBRARY_SYNCED.fire()
if any_local_changes:
LOCAL_LIBRARY_UPDATED.fire()