Skip to content

Commit 99b8f49

Browse files
committed
Improve support for stateless live components
Stop storing mock state objects in Redis
1 parent 063025e commit 99b8f49

File tree

3 files changed

+50
-9
lines changed

3 files changed

+50
-9
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## UNRELEASED
9+
10+
- Improved support for stateless live components. They don't store mock state objects in Redis anymore.
11+
812
## 1.8.0 (2023-12-18)
913

1014
- Added helper method StateAddress.with_component_id() to create a StateAddress with the same session ID, but a different component ID.

livecomponents/component.py

+43-8
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,33 @@ def get_command(self, command_name: str) -> Callable:
4545
)
4646
return command_func
4747

48+
def get_state(
49+
self, state_manager: StateManager, state_addr: StateAddress
50+
) -> State | None:
51+
"""Get the state of this component."""
52+
return state_manager.get_component_state(state_addr)
53+
54+
def get_or_create_state(
55+
self,
56+
state_manager: StateManager,
57+
state_addr: StateAddress,
58+
request: HttpRequest,
59+
component_kwargs: dict[str, Any],
60+
) -> State:
61+
"""Internal function to get or create the state of this component.
62+
63+
We used it to override the function for the stateless component
64+
where we don't need to store the state in Redis.
65+
"""
66+
return state_manager.get_or_create_component_state(
67+
request,
68+
state_addr,
69+
self.init_state,
70+
self.update_state,
71+
self.outer_context,
72+
component_kwargs,
73+
)
74+
4875
def get_context_data(
4976
self,
5077
own_id: str = DEFAULT_OWN_ID,
@@ -67,15 +94,9 @@ def get_context_data(
6794
component_id=component_id,
6895
)
6996
state_manager = get_state_manager()
70-
state = state_manager.get_or_create_component_state(
71-
request,
72-
state_addr,
73-
self.init_state,
74-
self.update_state,
75-
self.outer_context,
76-
component_kwargs,
97+
state = self.get_or_create_state(
98+
state_manager, state_addr, request, component_kwargs
7799
)
78-
79100
extra_context_request: ExtraContextRequest[State] = ExtraContextRequest(
80101
request=request,
81102
state=state,
@@ -170,6 +191,20 @@ class StatelessLiveComponent(LiveComponent[StatelessModel]):
170191
extra_context_request contains the state_manager and state_addr.
171192
"""
172193

194+
def get_state(
195+
self, state_manager: StateManager, state_addr: StateAddress
196+
) -> StatelessModel | None:
197+
return StatelessModel()
198+
199+
def get_or_create_state(
200+
self,
201+
state_manager: StateManager,
202+
state_addr: StateAddress,
203+
request: HttpRequest,
204+
component_kwargs: dict[str, Any],
205+
) -> StatelessModel:
206+
return StatelessModel()
207+
173208
def init_state(self, context: InitStateContext) -> StatelessModel:
174209
return StatelessModel()
175210

livecomponents/manager/manager.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,9 @@ def call_component_command(
200200
component_cls = self.get_component_class(state_addr.get_component_name())
201201
component_instance = component_cls()
202202

203-
state = self.get_component_state(state_addr)
203+
# Delegate fetching the state to the component instance because it may
204+
# want to decide not to fetch the state from Redis.
205+
state = component_instance.get_state(self, state_addr)
204206
if state is None:
205207
raise ValueError(f"Component state not found: {state_addr}")
206208

0 commit comments

Comments
 (0)