Radish alpha
r
Radicle web interface
Radicle
Git (anonymous pull)
Log in to clone via SSH
Simplify nodeStore, and make it part of the httpdStore
Sebastian Martinez committed 2 years ago
commit 54be2b78e410ff754fb51cfadbcce053dd0377e7
parent 7f4af6fb72bb1265c1c524b037e175f1a332b994
5 files changed +14 -113
modified src/App.svelte
@@ -3,7 +3,6 @@

  import * as router from "@app/lib/router";
  import * as httpd from "@app/lib/httpd";
-
  import * as node from "@app/lib/node";
  import { unreachable } from "@app/lib/utils";

  import Footer from "./App/Footer.svelte";
@@ -31,7 +30,6 @@
  const activeRouteStore = router.activeRouteStore;

  void httpd.initialize().finally(() => void router.loadFromLocation());
-
  void node.initialize();

  if (!window.VITEST && !window.PLAYWRIGHT && import.meta.env.PROD) {
    const plausible = Plausible({
modified src/App/Header.svelte
@@ -4,7 +4,6 @@
  import NodeInfo from "@app/App/Header/NodeInfo.svelte";
  import Authenticate from "./Header/Authenticate.svelte";
  import { httpdStore } from "@app/lib/httpd";
-
  import { nodeStore } from "@app/lib/node";
</script>

<style>
@@ -50,9 +49,7 @@

  <div class="right layout-desktop-flex">
    {#if $httpdStore.state !== "stopped"}
-
      {#if $nodeStore}
-
        <NodeInfo running={$nodeStore === "running"} />
-
      {/if}
+
      <NodeInfo running={$httpdStore.node === "running"} />
      <Authenticate />
    {/if}
    <Connect />
modified src/lib/httpd.ts
@@ -3,7 +3,6 @@ import { withTimeout, Mutex, E_CANCELED, E_TIMEOUT } from "async-mutex";

import { HttpdClient } from "@httpd-client";
import { config } from "@app/lib/config";
-
import { isLocal } from "@app/lib/utils";

export interface Session {
  id: string;
@@ -13,10 +12,11 @@ export interface Session {

export type HttpdState =
  | { state: "stopped" }
-
  | { state: "running" }
+
  | { state: "running"; node: "running" | "stopped" }
  | {
      state: "authenticated";
      session: Session;
+
      node: "running" | "stopped";
    };

const HTTPD_STATE_STORAGE_KEY = "httpdState";
@@ -24,13 +24,6 @@ const HTTPD_CUSTOM_PORT_KEY = "httpdCustomPort";

const store = writable<HttpdState>({ state: "stopped" });
export const httpdStore = derived(store, s => s);
-
export const authenticated = derived(store, s =>
-
  s.state === "authenticated" ? s : undefined,
-
);
-
export const authenticatedLocal = derived(
-
  store,
-
  s => (hostname: string) => s.state === "authenticated" && isLocal(hostname),
-
);

export const api = new HttpdClient({
  hostname: "127.0.0.1",
@@ -64,6 +57,7 @@ export async function authenticate(params: {
        sig: params.signature,
        pk: params.publicKey,
      });
+
      const { state: node } = await api.getNode();
      const sess = await api.session.getById(params.id);
      update({
        state: "authenticated",
@@ -72,6 +66,7 @@ export async function authenticate(params: {
          publicKey: params.publicKey,
          alias: sess.alias,
        },
+
        node,
      });
      return true;
    } catch (error) {
@@ -93,7 +88,8 @@ export async function disconnect() {

      try {
        await api.session.delete(httpd.session.id);
-
        update({ state: "running" });
+
        const { state: node } = await api.getNode();
+
        update({ state: "running", node });
      } catch (error) {
        console.error(error);
        update({ state: "stopped" });
@@ -124,6 +120,7 @@ async function checkState() {
  await stateMutex
    .runExclusive(async () => {
      try {
+
        const { state: node } = await api.getNode();
        if (httpdState && httpdState.state === "authenticated") {
          const sess = await api.session.getById(httpdState.session.id);
          const unixTimeInSeconds = Math.floor(Date.now() / 1000);
@@ -131,13 +128,12 @@ async function checkState() {
            sess.status === "unauthorized" ||
            sess.expiresAt < unixTimeInSeconds
          ) {
-
            update({ state: "running" });
+
            update({ state: "running", node });
          } else {
-
            update(httpdState);
+
            update({ ...httpdState, node });
          }
        } else {
-
          await api.getNodeInfo();
-
          update({ state: "running" });
+
          update({ state: "running", node });
        }
      } catch (error) {
        if (error instanceof TypeError && error.message !== "Failed to fetch") {
deleted src/lib/node.ts
@@ -1,91 +0,0 @@
-
import { derived, writable } from "svelte/store";
-
import { withTimeout, Mutex, E_CANCELED, E_TIMEOUT } from "async-mutex";
-

-
import { HttpdClient } from "@httpd-client";
-
import { config } from "@app/lib/config";
-

-
export type NodeState = "stopped" | "running";
-

-
const NODE_STATE_STORAGE_KEY = "nodeState";
-

-
const store = writable<NodeState>("stopped");
-
export const nodeStore = derived(store, s => s);
-

-
export const api = new HttpdClient({
-
  hostname: "127.0.0.1",
-
  port: config.nodes.defaultLocalHttpdPort,
-
  scheme: "http",
-
});
-

-
let pollHttpdStateHandle: number | undefined = undefined;
-

-
function update(state: NodeState) {
-
  window.localStorage.setItem(NODE_STATE_STORAGE_KEY, state);
-
  store.set(state);
-
}
-

-
const stateMutex = withTimeout(new Mutex(), 5_000);
-

-
async function checkState() {
-
  let nodeState: NodeState | null = null;
-
  const rawNodeState = window.localStorage.getItem(NODE_STATE_STORAGE_KEY);
-
  if (rawNodeState === "running" || rawNodeState === "stopped") {
-
    nodeState = rawNodeState;
-
  }
-

-
  await stateMutex
-
    .runExclusive(async () => {
-
      try {
-
        if (nodeState) {
-
          update(nodeState);
-
        }
-
        const node = await api.getNode();
-
        update(node.state);
-
      } catch (error) {
-
        if (error instanceof TypeError) {
-
          console.error(error);
-
        }
-
        update("stopped");
-
      }
-
    })
-
    .catch(error => {
-
      if (error !== E_CANCELED && error !== E_TIMEOUT) {
-
        throw error;
-
      }
-
    });
-
}
-

-
function pollSession() {
-
  if (pollHttpdStateHandle) {
-
    return;
-
  }
-

-
  pollHttpdStateHandle = window.setInterval(() => checkState(), 10_000);
-
}
-

-
export async function initialize() {
-
  // Sync session state changes with other open tabs and windows.
-
  addEventListener("storage", event => {
-
    if (
-
      event.key === NODE_STATE_STORAGE_KEY &&
-
      event.oldValue !== event.newValue
-
    ) {
-
      void checkState();
-
    }
-
  });
-

-
  await checkState();
-

-
  // Properly clean up setInterval and restart session polling when Vite
-
  // performs hot module reload on file changes.
-
  if (import.meta.hot) {
-
    import.meta.hot.accept();
-
    import.meta.hot.dispose(() => {
-
      clearInterval(pollHttpdStateHandle);
-
      pollHttpdStateHandle = undefined;
-
      pollSession();
-
    });
-
  }
-

-
  pollSession();
-
}
modified src/views/projects/Issues.svelte
@@ -4,7 +4,8 @@
  import { HttpdClient } from "@httpd-client";
  import { ISSUES_PER_PAGE } from "./router";
  import { closeFocused } from "@app/components/Popover.svelte";
-
  import { authenticatedLocal } from "@app/lib/httpd";
+
  import { httpdStore } from "@app/lib/httpd";
+
  import { isLocal } from "@app/lib/utils";

  import Button from "@app/components/Button.svelte";
  import DropdownList from "@app/components/DropdownList.svelte";
@@ -125,7 +126,7 @@
            </Link>
          </DropdownList>
        </Popover>
-
        {#if $authenticatedLocal(baseUrl.hostname)}
+
        {#if $httpdStore.state === "authenticated" && isLocal(baseUrl.hostname)}
          <div style="margin-left: auto;">
            <Link
              route={{