Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make a CodeHost state machine #1667

Merged
merged 3 commits into from
Nov 3, 2023
Merged

Make a CodeHost state machine #1667

merged 3 commits into from
Nov 3, 2023

Conversation

swankjesse
Copy link
Collaborator

This simplifies much of the internal complexity of TreehouseApp. We can also delete FakeCodeHost because the single implementation is suitable for unit testing.

Closes: #1660

@swankjesse
Copy link
Collaborator Author

I’d like to add tests before reviewing this.

import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.cancel
import kotlinx.coroutines.job
import kotlinx.coroutines.launch
import kotlinx.serialization.json.Json

internal class FakeCodeSession(
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I can refactor the ZiplineCodeSession state management to share a lot more code with this fake.

override fun cancel() {
if (canceled) return
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don’t like that these are being canceled multiple times. It’s not a bug, but it’s inelegant.

fun setUp() {
runBlocking {
codeHost.start()
eventLog.takeEvent("codeHost.collectCodeUpdates()")
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added an event for this so I can tell when we’re receiving new code and when we’re not. In this test it’s not that interesting!

content.unbind()
}

/** CodeHost doesn't have to stay resident forever. */
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is probably the most exciting thing about the PR. We can now shut down a Zipline completely and start it up again. That’ll be potentially great for saving memory.

@swankjesse swankjesse force-pushed the jwilson.1101.scope_to_code_session branch from 452ef54 to 87b9818 Compare November 3, 2023 03:29
@swankjesse swankjesse force-pushed the jwilson.1102.code_host branch from 79b46c1 to bbdeb4d Compare November 3, 2023 03:34
@swankjesse swankjesse marked this pull request as ready for review November 3, 2023 04:03
Base automatically changed from jwilson.1101.scope_to_code_session to trunk November 3, 2023 04:06
This simplifies much of the internal complexity of TreehouseApp.
We can also delete FakeCodeHost because the single implementation
is suitable for unit testing.

Closes: #1660
Also adopt CoroutineScope more aggressively in CodeSession
for lifecycle management.
@swankjesse swankjesse force-pushed the jwilson.1102.code_host branch from bbdeb4d to 64dc227 Compare November 3, 2023 04:07
@@ -62,7 +71,7 @@ public class TreehouseApp<A : AppService> private constructor(
* instance may be replaced if new code is loaded.
*/
public val zipline: Zipline?
get() = codeHost.session?.zipline
get() = (codeHost.codeSession as? ZiplineCodeSession)?.zipline
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is codeSession not being a ZiplineCodeSession valid?

If not, perhaps we can make CodeSession itself a type parameter?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lemme explore that in follow up!

Comment on lines +183 to +195
class Running<A : AppService>(
override val codeUpdatesScope: CoroutineScope,
override val codeSession: CodeSession<A>,
) : State<A>()

class Starting<A : AppService>(
override val codeUpdatesScope: CoroutineScope,
) : State<A>()

class Crashed<A : AppService>(
override val codeUpdatesScope: CoroutineScope,
) : State<A>()
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personally, I would've loved to see the states hoisted inside the respective states, in order to get the true benefits of making a state machine (i.e., it being easy to follow how one state gets to the next, a thing which is still difficult in this PR).

Apologies if that was a planned follow up!

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah lemme explore that in follow up.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A month later . . . we looked into this, and didn’t find something I loved!

@veyndan if you’d like to run with this, please do!

@swankjesse swankjesse enabled auto-merge (squash) November 3, 2023 14:36
@swankjesse swankjesse merged commit 4ed92bc into trunk Nov 3, 2023
8 checks passed
@swankjesse swankjesse deleted the jwilson.1102.code_host branch November 3, 2023 14:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Make TreehouseApp more state machiney
3 participants