|
@@ -13,6 +13,10 @@
|
|
#
|
|
#
|
|
# You should have received a copy of the GNU Affero General Public License
|
|
# You should have received a copy of the GNU Affero General Public License
|
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
+from typing import Optional
|
|
|
|
+import logging
|
|
|
|
+import asyncio
|
|
|
|
+
|
|
from mautrix.types import UserID, RoomID
|
|
from mautrix.types import UserID, RoomID
|
|
from mautrix.bridge import Bridge
|
|
from mautrix.bridge import Bridge
|
|
from mautrix.bridge.state_store.asyncpg import PgBridgeStateStore
|
|
from mautrix.bridge.state_store.asyncpg import PgBridgeStateStore
|
|
@@ -47,6 +51,12 @@ class InstagramBridge(Bridge):
|
|
state_store: PgBridgeStateStore
|
|
state_store: PgBridgeStateStore
|
|
provisioning_api: ProvisioningAPI
|
|
provisioning_api: ProvisioningAPI
|
|
|
|
|
|
|
|
+ periodic_reconnect_task: Optional[asyncio.Task]
|
|
|
|
+
|
|
|
|
+ def preinit(self) -> None:
|
|
|
|
+ self.periodic_reconnect_task = None
|
|
|
|
+ super().preinit()
|
|
|
|
+
|
|
def make_state_store(self) -> None:
|
|
def make_state_store(self) -> None:
|
|
self.state_store = PgBridgeStateStore(self.db, self.get_puppet, self.get_double_puppet)
|
|
self.state_store = PgBridgeStateStore(self.db, self.get_puppet, self.get_double_puppet)
|
|
|
|
|
|
@@ -71,8 +81,10 @@ class InstagramBridge(Bridge):
|
|
if self.config["bridge.resend_bridge_info"]:
|
|
if self.config["bridge.resend_bridge_info"]:
|
|
self.add_startup_actions(self.resend_bridge_info())
|
|
self.add_startup_actions(self.resend_bridge_info())
|
|
await super().start()
|
|
await super().start()
|
|
|
|
+ self.periodic_reconnect_task = self.loop.create_task(self._try_periodic_reconnect_loop())
|
|
|
|
|
|
def prepare_stop(self) -> None:
|
|
def prepare_stop(self) -> None:
|
|
|
|
+ self.periodic_reconnect_task.cancel()
|
|
self.add_shutdown_actions(user.stop_listen() for user in User.by_igpk.values())
|
|
self.add_shutdown_actions(user.stop_listen() for user in User.by_igpk.values())
|
|
self.log.debug("Stopping puppet syncers")
|
|
self.log.debug("Stopping puppet syncers")
|
|
for puppet in Puppet.by_custom_mxid.values():
|
|
for puppet in Puppet.by_custom_mxid.values():
|
|
@@ -86,6 +98,43 @@ class InstagramBridge(Bridge):
|
|
await portal.update_bridge_info()
|
|
await portal.update_bridge_info()
|
|
self.log.info("Finished re-sending bridge info state events")
|
|
self.log.info("Finished re-sending bridge info state events")
|
|
|
|
|
|
|
|
+ async def _try_periodic_reconnect_loop(self) -> None:
|
|
|
|
+ try:
|
|
|
|
+ await self._periodic_reconnect_loop()
|
|
|
|
+ except Exception:
|
|
|
|
+ self.log.exception("Fatal error in periodic reconnect loop")
|
|
|
|
+
|
|
|
|
+ async def _periodic_reconnect_loop(self) -> None:
|
|
|
|
+ log = logging.getLogger("mau.periodic_reconnect")
|
|
|
|
+ always_reconnect = self.config["bridge.periodic_reconnect.always"]
|
|
|
|
+ interval = self.config["bridge.periodic_reconnect.interval"]
|
|
|
|
+ if interval <= 0:
|
|
|
|
+ log.debug("Periodic reconnection is not enabled")
|
|
|
|
+ return
|
|
|
|
+ resync = bool(self.config["bridge.periodic_reconnect.resync"])
|
|
|
|
+ if interval < 600:
|
|
|
|
+ log.warning("Periodic reconnect interval is quite low (%d)", interval)
|
|
|
|
+ log.debug("Starting periodic reconnect loop")
|
|
|
|
+ while True:
|
|
|
|
+ try:
|
|
|
|
+ await asyncio.sleep(interval)
|
|
|
|
+ except asyncio.CancelledError:
|
|
|
|
+ log.debug("Periodic reconnect loop stopped")
|
|
|
|
+ return
|
|
|
|
+ log.info("Executing periodic reconnections")
|
|
|
|
+ for user in User.by_igpk.values():
|
|
|
|
+ if not user.is_connected and not always_reconnect:
|
|
|
|
+ log.debug("Not reconnecting %s: not connected", user.mxid)
|
|
|
|
+ continue
|
|
|
|
+ log.debug("Executing periodic reconnect for %s", user.mxid)
|
|
|
|
+ try:
|
|
|
|
+ await user.refresh(resync=resync)
|
|
|
|
+ except asyncio.CancelledError:
|
|
|
|
+ log.debug("Periodic reconnect loop stopped")
|
|
|
|
+ return
|
|
|
|
+ except Exception:
|
|
|
|
+ log.exception("Error while reconnecting", user.mxid)
|
|
|
|
+
|
|
async def get_portal(self, room_id: RoomID) -> Portal:
|
|
async def get_portal(self, room_id: RoomID) -> Portal:
|
|
return await Portal.get_by_mxid(room_id)
|
|
return await Portal.get_by_mxid(room_id)
|
|
|
|
|