Skip to content

Commit 2a9f2eb

Browse files
committed
feat(migrations): downgrade
1 parent c2203af commit 2a9f2eb

7 files changed

Lines changed: 73 additions & 0 deletions

File tree

questionpy_common/api/qtype.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,10 @@ def create_question_from_state(self, question_state: str) -> QuestionInterface:
6868
def upgrade(self, question_state: str) -> str:
6969
"""Upgrade the given question state to the question state version of the main package."""
7070

71+
@abstractmethod
72+
def downgrade(self, question_state: str, to: int) -> str:
73+
"""Downgrade the given question state to the provided question state version of the main package."""
74+
7175
@abstractmethod
7276
def sidegrade(self, question_state: str) -> str:
7377
"""Sidegrade the given question state to the version used by the main package."""

questionpy_server/models.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,11 @@ class QuestionUpgradeArguments(RequestBaseData):
8989
question_state: str
9090

9191

92+
class QuestionDowngradeArguments(RequestBaseData):
93+
question_state: str
94+
to: int
95+
96+
9297
class QuestionSidegradeArguments(RequestBaseData):
9398
question_state: str
9499

questionpy_server/web/_routes/_packages.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from questionpy_common.api.question import LmsPermissions
88
from questionpy_server.models import (
99
QuestionCreateArguments,
10+
QuestionDowngradeArguments,
1011
QuestionEditFormResponse,
1112
QuestionSidegradeArguments,
1213
QuestionUpgradeArguments,
@@ -91,6 +92,17 @@ async def post_question_upgrade(request: web.Request, package: Package, data: Qu
9192
return pydantic_json_response(data=new_question_state)
9293

9394

95+
@package_routes.post(r"/packages/{package_hash:\w+}/question/downgrade")
96+
@ensure_required_parts
97+
async def post_question_downgrade(
98+
request: web.Request, package: Package, data: QuestionDowngradeArguments
99+
) -> web.Response:
100+
async with worker_context(request, package, data) as context:
101+
new_question_state = await context.worker.downgrade_question(context.request_info, data.question_state, data.to)
102+
103+
return pydantic_json_response(data=new_question_state)
104+
105+
94106
@package_routes.post(r"/packages/{package_hash:\w+}/question/sidegrade")
95107
@ensure_required_parts
96108
async def post_question_sidegrade(

questionpy_server/worker/__init__.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,20 @@ async def upgrade_question(self, request_info: RequestInfo, question_state: str)
163163
Migrated question state.
164164
"""
165165

166+
@abstractmethod
167+
async def downgrade_question(self, request_info: RequestInfo, question_state: str, to: int) -> QuestionMigrated:
168+
"""Downgrade the given question state to the question state version of this package.
169+
170+
Args:
171+
request_info: Information about the current request.
172+
question_state: The question state with the same question state version as this package which should be
173+
downgraded.
174+
to: The question state version to downgrade to.
175+
176+
Returns:
177+
Migrated question state.
178+
"""
179+
166180
@abstractmethod
167181
async def sidegrade_question(self, request_info: RequestInfo, question_state: str) -> QuestionMigrated:
168182
"""Sidegrade the given question state to the question state version of this package.

questionpy_server/worker/impl/_base.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
from questionpy_server.worker.runtime.messages import (
3535
BaseWorkerError,
3636
CreateQuestionFromOptions,
37+
DowngradeQuestion,
3738
Exit,
3839
GetOptionsForm,
3940
GetQPyPackageManifest,
@@ -262,6 +263,16 @@ async def upgrade_question(self, request_info: RequestInfo, question_state: str)
262263

263264
return QuestionMigrated(question_state=ret.question_state)
264265

266+
async def downgrade_question(self, request_info: RequestInfo, question_state: str, to: int) -> QuestionMigrated:
267+
msg = DowngradeQuestion(
268+
request_info=request_info,
269+
question_state=question_state,
270+
target_question_state_version=to,
271+
)
272+
ret = await self.send_and_wait_for_response(msg, DowngradeQuestion.Response)
273+
274+
return QuestionMigrated(question_state=ret.question_state)
275+
265276
async def sidegrade_question(self, request_info: RequestInfo, question_state: str) -> QuestionMigrated:
266277
msg = SidegradeQuestion(
267278
request_info=request_info,

questionpy_server/worker/runtime/manager.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
from questionpy_server.worker.runtime.connection import WorkerToServerConnection
2727
from questionpy_server.worker.runtime.messages import (
2828
CreateQuestionFromOptions,
29+
DowngradeQuestion,
2930
Exit,
3031
GetOptionsForm,
3132
GetQPyPackageManifest,
@@ -117,6 +118,7 @@ def __init__(self, server_connection: WorkerToServerConnection):
117118
GetOptionsForm.message_id: self.on_msg_get_options_form_definition,
118119
CreateQuestionFromOptions.message_id: self.on_msg_create_question_from_options,
119120
UpgradeQuestion.message_id: self.on_msg_upgrade_question,
121+
DowngradeQuestion.message_id: self.on_msg_downgrade_question,
120122
SidegradeQuestion.message_id: self.on_msg_sidegrade_question,
121123
StartAttempt.message_id: self.on_msg_start_attempt,
122124
ViewAttempt.message_id: self.on_msg_view_attempt,
@@ -269,6 +271,18 @@ def on_msg_upgrade_question(self, msg: UpgradeQuestion) -> UpgradeQuestion.Respo
269271
migrated_question_state = self._question_type.upgrade(msg.question_state)
270272
return UpgradeQuestion.Response(question_state=migrated_question_state)
271273

274+
def on_msg_downgrade_question(self, msg: DowngradeQuestion) -> DowngradeQuestion.Response:
275+
if not self._env:
276+
self._raise_not_initialized(msg)
277+
if not self._question_type:
278+
self._raise_no_main_package_loaded(msg)
279+
280+
with self._with_request_info(msg, msg.request_info):
281+
migrated_question_state = self._question_type.downgrade(
282+
msg.question_state, msg.target_question_state_version
283+
)
284+
return DowngradeQuestion.Response(question_state=migrated_question_state)
285+
272286
def on_msg_sidegrade_question(self, msg: SidegradeQuestion) -> SidegradeQuestion.Response:
273287
if not self._env:
274288
self._raise_not_initialized(msg)

questionpy_server/worker/runtime/messages.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ class MessageIds(IntEnum):
3838

3939
CREATE_QUESTION = 40
4040
UPGRADE_QUESTION = 41
41+
DOWNGRADE_QUESTION = 42
4142
SIDEGRADE_QUESTION = 43
4243

4344
START_ATTEMPT = 50
@@ -54,6 +55,7 @@ class MessageIds(IntEnum):
5455

5556
RETURN_CREATE_QUESTION = 1040
5657
RETURN_UPGRADE_QUESTION = 1041
58+
RETURN_DOWNGRADE_QUESTION = 1042
5759
RETURN_SIDEGRADE_QUESTION = 1043
5860

5961
RETURN_START_ATTEMPT = 1050
@@ -223,6 +225,17 @@ class Response(MessageToServer):
223225
question_state: str
224226

225227

228+
class DowngradeQuestion(MessageToWorker):
229+
message_id: ClassVar[MessageIds] = MessageIds.DOWNGRADE_QUESTION
230+
request_info: RequestInfo
231+
question_state: str
232+
target_question_state_version: int
233+
234+
class Response(MessageToServer):
235+
message_id: ClassVar[MessageIds] = MessageIds.RETURN_DOWNGRADE_QUESTION
236+
question_state: str
237+
238+
226239
class SidegradeQuestion(MessageToWorker):
227240
message_id: ClassVar[MessageIds] = MessageIds.SIDEGRADE_QUESTION
228241
request_info: RequestInfo

0 commit comments

Comments
 (0)