Skip to content

Commit

Permalink
feat: use server-sent events instead of websockets (#172)
Browse files Browse the repository at this point in the history
* feat: use server sent events instead of websockets

Server Sent Events are conceptually simpler and use the HTTP protocol.
This makes them easier for self-hosters to use as they don't need to
modify their reverse proxies (like nginx) to use them like websockets.
I think this mostly impacted users who used subpaths rather than
subdomains.

We don't really need bidirectional communication, rather just server
to client because we don't know when the IRC server messages will
be processed. The messages that were previously sent over websocket
have been moved to API endpoints (search / download).

* chore: remove gorilla/websocket
  • Loading branch information
evan-buss authored Jun 30, 2024
1 parent 115ebd2 commit e6bc149
Show file tree
Hide file tree
Showing 24 changed files with 428 additions and 590 deletions.
Empty file modified .devcontainer/setup.sh
100644 → 100755
Empty file.
2 changes: 1 addition & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"request": "launch",
"mode": "debug",
"program": "cmd/openbooks",
"args": ["server", "--log", "--server", "localhost", "--persist"]
"args": ["server", "--log", "--tls", "false", "--server", "localhost:6667", "--name", "dev-user"]
},
{
"name": "Launch OpenBooks CLI",
Expand Down
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ require (
github.com/go-chi/chi/v5 v5.0.7
github.com/golang/snappy v0.0.4 // indirect
github.com/google/uuid v1.3.0
github.com/gorilla/websocket v1.5.0
github.com/mholt/archiver/v3 v3.5.1
github.com/nwaples/rardecode v1.1.3 // indirect
github.com/rs/cors v1.8.2
Expand All @@ -28,6 +27,7 @@ require (
require (
github.com/davecgh/go-spew v1.1.1
github.com/inkeliz/gowebview v1.0.1
github.com/r3labs/sse/v2 v2.10.0
github.com/testcontainers/testcontainers-go v0.17.0
gopkg.in/irc.v4 v4.0.0
)
Expand Down Expand Up @@ -73,5 +73,6 @@ require (
google.golang.org/genproto v0.0.0-20220617124728-180714bec0ad // indirect
google.golang.org/grpc v1.47.0 // indirect
google.golang.org/protobuf v1.28.0 // indirect
gopkg.in/cenkalti/backoff.v1 v1.1.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
7 changes: 5 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,6 @@ github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc=
Expand Down Expand Up @@ -160,6 +158,8 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/r3labs/sse/v2 v2.10.0 h1:hFEkLLFY4LDifoHdiCN/LlGBAdVJYsANaLqNYa1l/v0=
github.com/r3labs/sse/v2 v2.10.0/go.mod h1:Igau6Whc+F17QUgML1fYe1VPZzTV6EMCnYktEmkNJ7I=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.3.4 h1:3Z3Eu6FGHZWSfNKJTOUiPatWwfc7DzJRU04jFUqJODw=
github.com/rivo/uniseg v0.3.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
Expand Down Expand Up @@ -228,6 +228,7 @@ golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73r
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191116160921-f9c825593386/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
Expand Down Expand Up @@ -318,6 +319,8 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/cenkalti/backoff.v1 v1.1.0 h1:Arh75ttbsvlpVA7WtVpH4u9h6Zl46xuptxqLxPiSo4Y=
gopkg.in/cenkalti/backoff.v1 v1.1.0/go.mod h1:J6Vskwqd+OMVJl8C33mmtxTBs2gyzfv7UDAkHu8BrjI=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/irc.v4 v4.0.0 h1:5jsLkU2Tg+R2nGNqmkGCrciasyi4kNkDXhyZD+C31yY=
Expand Down
10 changes: 7 additions & 3 deletions mock/operator.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@ package mock

import (
"context"
"gopkg.in/irc.v4"
"log"
"math/rand"
"net"
"os"
"strings"
"time"

"gopkg.in/irc.v4"
)

type Config struct {
Expand Down Expand Up @@ -58,8 +59,11 @@ func NewOperator(config *Config) *Operator {

func (o *Operator) Handler(client *irc.Client, message *irc.Message) {
if strings.HasPrefix(message.Trailing(), "@search") {
query := strings.SplitN(message.Trailing(), " ", 2)[1]
o.log.Printf("Search for '%s'\n", query)
queryParts := strings.SplitN(message.Trailing(), " ", 2)
if len(queryParts) == 1 {
return
}
o.log.Printf("Search for '%s'\n", queryParts[1])

dccString := o.dccManager.ServeFile("SearchBot_results_for_ the great gatsby.txt.zip")

Expand Down
88 changes: 41 additions & 47 deletions server/app/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion server/app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"@mantine/hooks": "^7.1.2",
"@mantine/notifications": "^7.1.2",
"@phosphor-icons/react": "^2.0.13",
"@reduxjs/toolkit": "^1.9.6",
"@reduxjs/toolkit": "^2.2.6",
"@tanstack/match-sorter-utils": "^8.8.4",
"@tanstack/react-table": "^8.10.3",
"@tanstack/react-virtual": "^3.0.0-beta.62",
Expand Down
19 changes: 8 additions & 11 deletions server/app/src/components/sidebar/History.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { useAutoAnimate } from "@formkit/auto-animate/react";
import {
Badge,
Button,
Expand All @@ -9,22 +10,18 @@ import {
Tooltip
} from "@mantine/core";
import { Eye, EyeSlash, MagnifyingGlass, Trash } from "@phosphor-icons/react";
import { useSelector } from "react-redux";
import {
deleteHistoryItem,
HistoryItem,
selectHistory
removeResults,
setActiveItem
} from "../../state/historySlice";
import { setActiveItem } from "../../state/stateSlice";
import { AppDispatch, useAppDispatch, useAppSelector } from "../../state/store";
import classes from "./SidebarButton.module.css";
import { conditionalAttribute } from "../../utils/attribute-helper";
import { useAutoAnimate } from "@formkit/auto-animate/react";
import classes from "./SidebarButton.module.css";

export default function History() {
const history = useSelector(selectHistory);
const activeTS =
useAppSelector((store) => store.state.activeItem?.timestamp) ?? -1;
const history = useAppSelector((store) => store.history.items);
const activeTS = useAppSelector((store) => store.history.active);
const dispatch = useAppDispatch();
const [parent] = useAutoAnimate(/* optional config */);

Expand All @@ -51,7 +48,7 @@ export default function History() {
}

type Props = {
activeTS: number;
activeTS: number | undefined;
item: HistoryItem;
dispatch: AppDispatch;
};
Expand Down Expand Up @@ -107,7 +104,7 @@ function HistoryCard({ activeTS, item, dispatch }: Props) {
<Menu.Item
color="red"
leftSection={<Trash size={18} weight="bold" />}
onClick={() => dispatch(deleteHistoryItem(item.timestamp))}>
onClick={() => dispatch(removeResults(item.timestamp))}>
Delete item
</Menu.Item>
</Menu.Dropdown>
Expand Down
2 changes: 1 addition & 1 deletion server/app/src/components/sidebar/Library.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import classes from "./SidebarButton.module.css";
import { useAutoAnimate } from "@formkit/auto-animate/react";

export default function Library() {
const { data, isLoading, isSuccess, isError } = useGetBooksQuery(null);
const { data, isLoading, isSuccess, isError } = useGetBooksQuery();
const [parent] = useAutoAnimate(/* optional config */);

if (isLoading && !data) {
Expand Down
20 changes: 11 additions & 9 deletions server/app/src/components/tables/BookTable.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import { Button, Indicator, Loader, Text, Tooltip } from "@mantine/core";
import { createColumnHelper, Table } from "@tanstack/react-table";
import React, { useCallback, useMemo, useState } from "react";
import { Table, createColumnHelper } from "@tanstack/react-table";
import { useCallback, useMemo, useState } from "react";
import { useSelector } from "react-redux";
import { useGetServersQuery } from "../../state/api";
import { useDownloadMutation, useGetServersQuery } from "../../state/api";
import { BookDetail } from "../../state/messages";
import { sendDownload } from "../../state/stateSlice";
import { RootState, useAppDispatch } from "../../state/store";
import { RootState } from "../../state/store";
import { DataTableColumnHeader } from "./DataTable/ColumnHeader";
import DataTable from "./DataTable/DataTable";
import ToolbarFacetFilter from "./DataTable/ToolbarFacetFilter";
Expand All @@ -18,7 +17,10 @@ interface BookTableProps {
}

export default function BookTable({ books }: BookTableProps) {
const { data: servers } = useGetServersQuery(null);
const { data: servers } = useGetServersQuery(undefined, {
pollingInterval: 5000,
skipPollingIfUnfocused: true
});

const columns = useMemo(
() => [
Expand All @@ -27,7 +29,7 @@ export default function BookTable({ books }: BookTableProps) {
<DataTableColumnHeader column={props.column} title="Server" />
),
cell: (props) => {
const online = servers?.includes(props.getValue());
const online = servers && servers.has(props.getValue());
return (
<Tooltip position="top-start" label={online ? "Online" : "Offline"}>
<Indicator
Expand Down Expand Up @@ -123,7 +125,7 @@ export default function BookTable({ books }: BookTableProps) {
}

function DownloadButton({ book }: { book: string }) {
const dispatch = useAppDispatch();
const [downloadMutation] = useDownloadMutation();

const [clicked, setClicked] = useState(false);
const isInFlight = useSelector((state: RootState) =>
Expand All @@ -133,7 +135,7 @@ function DownloadButton({ book }: { book: string }) {
// Prevent hitting the same button multiple times
const onClick = () => {
if (clicked) return;
dispatch(sendDownload(book));
downloadMutation(book);
setClicked(true);
};

Expand Down
4 changes: 2 additions & 2 deletions server/app/src/components/tables/Facets.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ export function ServerFacetEntry({
selected,
style
}: FacetEntryProps) {
const { data: servers } = useGetServersQuery(null);
const serverOnline = servers?.includes(entry) ?? false;
const { data: servers } = useGetServersQuery();
const serverOnline = servers && servers.has(entry);

return (
<Button
Expand Down
Loading

0 comments on commit e6bc149

Please sign in to comment.