Skip to content

Commit 56cbd4e

Browse files
committed
Stopping actual stops now, I hope.
1 parent 9b8cf2d commit 56cbd4e

File tree

8 files changed

+93
-100
lines changed

8 files changed

+93
-100
lines changed

src/flowco/__main__.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
from flowco.util.output import Output, error, log, log_timestamp, message, logger
2626

2727
from flowco.util.errors import FlowcoError
28-
from flowco.util.stopper import Stopper
2928
from flowco.util.text import md_to_html
3029
from flowthon.flowthon import FlowthonProgram
3130

@@ -394,15 +393,13 @@ def main(page: Optional[Page] = None, argv: List[str] = sys.argv[1:]):
394393
session.set(
395394
output=Output(),
396395
costs=CostTracker(),
397-
stopper=Stopper(),
398396
shells=PythonShells(),
399397
filesystem=SessionFileSystem(f"file://{os.getcwd()}"),
400398
)
401399
log_timestamp()
402400

403401
try:
404-
with session.get("stopper", Stopper):
405-
main_core(page=page, argv=argv)
402+
main_core(page=page, argv=argv)
406403
except FlowcoError as e:
407404
error(e)
408405
finally:

src/flowco/builder/build.py

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
from flowco.dataflow.phase import Phase
1010
from flowco.session.session import session
1111
from flowco.util.output import error, log, warn, logger
12-
from flowco.util.stopper import Stopper
1312
from typing import (
1413
Callable,
1514
Dict,
@@ -194,6 +193,7 @@ def build_with_worklist(
194193
graph: DataFlowGraph,
195194
target_phase: Phase,
196195
node_ids: List[str] | str | None,
196+
should_stop: Callable[[], bool] = lambda: False,
197197
) -> Iterator[BuildUpdate]:
198198

199199
node_ids = graph.listify_node_ids(node_ids)
@@ -205,11 +205,11 @@ def build_with_worklist(
205205

206206
if config.sequential:
207207
yield from self.build_with_worklist_sequential(
208-
pass_config, graph, target_phase, node_ids
208+
pass_config, graph, target_phase, node_ids, should_stop
209209
)
210210
else:
211211
yield from self.build_with_worklist_parallel(
212-
pass_config, graph, target_phase, node_ids
212+
pass_config, graph, target_phase, node_ids, should_stop
213213
)
214214

215215
def build_with_worklist_sequential(
@@ -218,6 +218,7 @@ def build_with_worklist_sequential(
218218
graph: DataFlowGraph,
219219
target_phase: Phase,
220220
node_ids: List[str] | str | None,
221+
should_stop: Callable[[], bool],
221222
) -> Iterator[BuildUpdate]:
222223

223224
@dataclass
@@ -236,7 +237,7 @@ def process_workitem(graph: DataFlowGraph, work_item: WorkItem):
236237
node = graph[node_id]
237238

238239
with logger(f"{node_id}:{node.pill}"):
239-
if session.get("stopper", Stopper).should_stop():
240+
if should_stop():
240241
return NodeResult(work_item, node, node, "Stopped")
241242

242243
node.build_status = phase_to_message.get(
@@ -322,8 +323,7 @@ def submit_items(current_worklist: Dict[WorkItem, List[WorkItem]]):
322323
current_worklist = submit_items(worklist)
323324

324325
with logger("Running worklist"):
325-
stopper = session.get("stopper", Stopper)
326-
while len(done) < len(worklist) and not stopper.should_stop():
326+
while len(done) < len(worklist) and not should_stop():
327327
try:
328328
log(f"Building: {len(worklist.keys()) - len(done)} steps")
329329
item = in_flight.pop(0)
@@ -372,6 +372,7 @@ def build_with_worklist_parallel(
372372
graph: DataFlowGraph,
373373
target_phase: Phase,
374374
node_ids: List[str] | str | None,
375+
should_stop: Callable[[], bool],
375376
) -> Iterator[BuildUpdate]:
376377

377378
@dataclass
@@ -396,7 +397,7 @@ def process_workitem(graph: DataFlowGraph, work_item: WorkItem):
396397

397398
with buffer_output(f"{node.pill}") as buffer:
398399
with logger(f"Starting"):
399-
if session.get("stopper", Stopper).should_stop():
400+
if should_stop():
400401
result_queue.put(
401402
NodeResult(work_item, node, node, "Stopped")
402403
)
@@ -520,8 +521,7 @@ def submit_items(current_worklist: Dict[WorkItem, List[WorkItem]]):
520521
current_worklist = submit_items(worklist)
521522

522523
with logger("Running worklist"):
523-
stopper = session.get("stopper", Stopper)
524-
while len(done) < len(worklist) and not stopper.should_stop():
524+
while len(done) < len(worklist) and not should_stop():
525525
try:
526526
log(f"Remaining: {len(worklist.keys()) - len(done)} steps")
527527
result = result_queue.get()
@@ -553,7 +553,8 @@ def submit_items(current_worklist: Dict[WorkItem, List[WorkItem]]):
553553
except Exception as e:
554554
error(e)
555555
raise e
556-
if stopper.should_stop():
556+
557+
if should_stop():
557558
executor.shutdown(wait=False, cancel_futures=True)
558559
log(f"Stopping!")
559560

src/flowco/ui/authenticate.py

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -49,29 +49,25 @@ def purge_stale_entries(cache_dict):
4949

5050

5151
def sign_in(authorization_url: str):
52-
instructions = textwrap.dedent(
53-
"""\
54-
# Flowco!
52+
release = os.getenv("RELEASE_VERSION", "unknown")
53+
commit_sha = os.getenv("COMMIT_SHA", "unknown")[:7]
54+
build_date = os.getenv("BUILD_DATE", "unknown")
5555

56+
instructions = textwrap.dedent(
57+
f"""\
58+
# Flowco {release}!
59+
5660
* Flowco uses Google Sign-In to authenticate users.
5761
* Your email address will be used to create a unique account.
5862
* Flowco uses an Amazon S3 bucket to store all user files.
63+
* Click the "Report Bug" whenever you see anything fishy!
5964
65+
[Version Release Notes](https://github.com/stephenfreund/flowco/releases)
6066
"""
6167
)
6268
# st.write(f"Please sign in to continue.")
6369
st.write(instructions)
6470
st.link_button("Sign In", authorization_url)
65-
st.divider()
66-
# Read the commit SHA and build date from environment variables
67-
release = os.getenv("RELEASE_VERSION", "unknown")
68-
commit_sha = os.getenv("COMMIT_SHA", "unknown")[:7]
69-
build_date = os.getenv("BUILD_DATE", "unknown")
70-
71-
st.write(f"Release {release}, {build_date}")
72-
st.page_link(
73-
"https://github.com/stephenfreund/flowco/releases", label="Release Notes"
74-
)
7571

7672

7773
# Function to fetch user information from id_token

src/flowco/ui/page_files/build_page.py

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,7 @@ def toggle_building(
225225
st.session_state.builder_progress = 0
226226
else:
227227
builder.stop()
228+
self.clear_builder_and_reset_state()
228229

229230
def get_builder_updates(self):
230231
ui_page: UIPage = st.session_state.ui_page
@@ -284,25 +285,27 @@ def fini(self):
284285
if builder is not None:
285286
if not builder.is_alive():
286287
self.get_builder_updates()
287-
st.session_state.force_update = True
288-
st.session_state.builder = None
289-
# set all node build_statuses to None
290-
ui_page: UIPage = st.session_state.ui_page
291-
dfg = ui_page.dfg()
292-
dfg = dfg.update(
293-
nodes=[
294-
x.update(
295-
build_status=None,
296-
)
297-
for x in dfg.nodes
298-
]
299-
)
300-
ui_page.update_dfg(dfg)
288+
self.clear_builder_and_reset_state()
301289
st.rerun()
302290
else:
303291
time.sleep(0.25)
304292
st.rerun()
305293

294+
def clear_builder_and_reset_state(self):
295+
st.session_state.force_update = True
296+
st.session_state.builder = None
297+
ui_page: UIPage = st.session_state.ui_page
298+
dfg = ui_page.dfg()
299+
dfg = dfg.update(
300+
nodes=[
301+
x.update(
302+
build_status=None,
303+
)
304+
for x in dfg.nodes
305+
]
306+
)
307+
ui_page.update_dfg(dfg)
308+
306309
@st.dialog("Edit Description", width="large")
307310
def edit_description(self):
308311
ui_page: UIPage = st.session_state.ui_page

src/flowco/ui/ui_builder.py

Lines changed: 33 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,11 @@
1-
from queue import Empty, Queue
1+
from queue import Queue
22
import threading
3-
from typing import List
3+
from typing import Callable, List
44
from flowco.builder.build import BuildEngine, BuildUpdate, PassConfig
5-
from flowco.dataflow.dfg import DataFlowGraph
65
from flowco.dataflow.phase import Phase
76
from flowco.page.page import Page
8-
from flowco.pythonshell.shells import PythonShells
97
from flowco.session.session import session
10-
from flowco.util.output import log, logger
11-
from flowco.util.stopper import Stopper
8+
from flowco.util.output import log
129

1310

1411
def run(
@@ -18,32 +15,25 @@ def run(
1815
node_ids: str | List[str] | None,
1916
target_phase: Phase,
2017
queue: Queue,
18+
should_stop: Callable[[], bool],
2119
):
2220

23-
with session.get("stopper", Stopper):
24-
with page:
25-
for build_updated in engine.build_with_worklist(
26-
build_config, page.dfg, target_phase, node_ids
27-
):
28-
# log(
29-
# f"Putting build_updated in queue. Remaining: {build_updated.steps_remaining}"
30-
# )
31-
# if session.get("stopper", Stopper).should_stop():
32-
# log("Stopping build early.")
33-
# return
34-
queue.put(build_updated)
21+
with page:
22+
for build_updated in engine.build_with_worklist(
23+
build_config, page.dfg, target_phase, node_ids, should_stop
24+
):
25+
queue.put(build_updated)
3526

36-
log("Waiting for no unfinished tasks.")
37-
with queue.all_tasks_done:
38-
if queue.unfinished_tasks:
39-
if queue.all_tasks_done.wait(3):
40-
log("All tasks done.")
41-
else:
42-
log("Timeout waiting for tasks to finish.")
27+
log("Waiting for no unfinished tasks.")
28+
with queue.all_tasks_done:
29+
if queue.unfinished_tasks:
30+
# Just wait a bit for the build page to clear out pending updates...
31+
if queue.all_tasks_done.wait(3):
32+
log("All tasks done.")
33+
else:
34+
log("Timeout waiting for tasks to finish.")
4335

44-
# queue.join()
45-
46-
log("Done building.")
36+
log("Done building.")
4737

4838

4939
class Builder:
@@ -77,10 +67,20 @@ def __init__(
7767
name = ", ".join([page.dfg[x].pill for x in node_ids])
7868
self.message = f"{verb} {name}..."
7969

70+
self.stopped = False
71+
8072
self.queue = Queue[BuildUpdate]()
8173
self.thread = threading.Thread(
8274
target=run,
83-
args=(builder, page, build_config, node_ids, target_phase, self.queue),
75+
args=(
76+
builder,
77+
page,
78+
build_config,
79+
node_ids,
80+
target_phase,
81+
self.queue,
82+
self.should_stop,
83+
),
8484
)
8585
setattr(self.thread, "flowco_session", session.get_session())
8686
self.thread.start()
@@ -100,6 +100,8 @@ def update_done(self) -> None:
100100
def is_alive(self) -> bool:
101101
return self.thread.is_alive()
102102

103+
def should_stop(self) -> bool:
104+
return self.stopped
105+
103106
def stop(self) -> None:
104-
with logger("Stopping builder"):
105-
session.get("stopper", Stopper).stop()
107+
self.stopped = True

src/flowco/ui/ui_main.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
from flowco.util.output import Output, error, log_timestamp
1414

1515
from flowco.session.session import StreamlitSession, session
16-
from flowco.util.stopper import Stopper
1716

1817

1918
def init_service():
@@ -35,7 +34,6 @@ def init_service():
3534
session.set(
3635
output=Output(),
3736
costs=CostTracker(),
38-
stopper=Stopper(),
3937
shells=PythonShells(),
4038
filesystem=SessionFileSystem(f"file://{page_path}"),
4139
)
@@ -73,7 +71,6 @@ def init_service():
7371
session.set(
7472
output=Output(),
7573
costs=CostTracker(),
76-
stopper=Stopper(),
7774
shells=PythonShells(),
7875
filesystem=SessionFileSystem(f"file://{page_path}"),
7976
)

src/flowco/util/stopper.py

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,28 @@
1-
import threading
1+
# import threading
22

33

4-
class Stopper:
4+
# class Stopper:
55

6-
def __init__(self):
7-
self._stop_flag = False
8-
self._nesting_level = 0
9-
self._lock = threading.RLock()
6+
# def __init__(self):
7+
# self._stop_flag = False
8+
# self._nesting_level = 0
9+
# self._lock = threading.RLock()
1010

11-
def __enter__(self):
12-
with self._lock:
13-
if self._nesting_level == 0:
14-
self._stop_flag = False
15-
self._nesting_level += 1
16-
return self
11+
# def __enter__(self):
12+
# with self._lock:
13+
# if self._nesting_level == 0:
14+
# self._stop_flag = False
15+
# self._nesting_level += 1
16+
# return self
1717

18-
def __exit__(self, exc_type, exc_value, traceback):
19-
with self._lock:
20-
self._nesting_level -= 1
18+
# def __exit__(self, exc_type, exc_value, traceback):
19+
# with self._lock:
20+
# self._nesting_level -= 1
2121

22-
def stop(self):
23-
with self._lock:
24-
self._stop_flag = True
22+
# def stop(self):
23+
# with self._lock:
24+
# self._stop_flag = True
2525

26-
def should_stop(self):
27-
with self._lock:
28-
return self._stop_flag
26+
# def should_stop(self):
27+
# with self._lock:
28+
# return self._stop_flag

0 commit comments

Comments
 (0)