Roll back plugin update if starting instances fails

This commit is contained in:
Tulir Asokan 2022-03-26 14:00:43 +02:00
parent 4d8e1475e6
commit adc892aa0d

View file

@ -15,6 +15,7 @@
# 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 io import BytesIO from io import BytesIO
from time import time from time import time
import logging
import os.path import os.path
import re import re
import traceback import traceback
@ -26,6 +27,8 @@ from ...loader import MaubotZipImportError, PluginLoader, ZippedPluginLoader
from .base import get_config, routes from .base import get_config, routes
from .responses import resp from .responses import resp
log = logging.getLogger("maubot.server.upload")
@routes.put("/plugin/{id}") @routes.put("/plugin/{id}")
async def put_plugin(request: web.Request) -> web.Response: async def put_plugin(request: web.Request) -> web.Response:
@ -103,12 +106,29 @@ async def upload_replacement_plugin(
try: try:
await plugin.reload(new_path=path) await plugin.reload(new_path=path)
except MaubotZipImportError as e: except MaubotZipImportError as e:
log.exception(f"Error loading updated version of {plugin.meta.id}, rolling back")
try: try:
await plugin.reload(new_path=old_path) await plugin.reload(new_path=old_path)
await plugin.start_instances() await plugin.start_instances()
except MaubotZipImportError: except MaubotZipImportError:
pass log.warning(f"Failed to roll back update of {plugin.meta.id}", exc_info=True)
finally:
ZippedPluginLoader.trash(path, reason="failed_update")
return resp.plugin_import_error(str(e), traceback.format_exc()) return resp.plugin_import_error(str(e), traceback.format_exc())
await plugin.start_instances() try:
await plugin.start_instances()
except Exception as e:
log.exception(f"Error starting {plugin.meta.id} instances after update, rolling back")
try:
await plugin.stop_instances()
await plugin.reload(new_path=old_path)
await plugin.start_instances()
except Exception:
log.warning(f"Failed to roll back update of {plugin.meta.id}", exc_info=True)
finally:
ZippedPluginLoader.trash(path, reason="failed_update")
return resp.plugin_reload_error(str(e), traceback.format_exc())
log.debug(f"Successfully updated {plugin.meta.id}, moving old version to trash")
ZippedPluginLoader.trash(old_path, reason="update") ZippedPluginLoader.trash(old_path, reason="update")
return resp.updated(plugin.to_dict()) return resp.updated(plugin.to_dict())