Skip to content

Commit

Permalink
Merge pull request #13 from PatrickRWells/server-settings
Browse files Browse the repository at this point in the history
Better Server Settings Management
  • Loading branch information
AstroPatty authored Feb 8, 2024
2 parents 69fe606 + 659a07a commit 266abff
Show file tree
Hide file tree
Showing 10 changed files with 282 additions and 242 deletions.
52 changes: 22 additions & 30 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,23 +29,21 @@ jobs:
matrix:
target: [x86_64-unknown-linux-gnu, aarch64-unknown-linux-gnu]
steps:
- uses: actions/checkout@v3
- uses: actions-rs/toolchain@v1
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
toolchain: stable
target: ${{ matrix.target }}
override: true
- uses: actions-rs/cargo@v1
with:
use-cross: true
command: build
args: --release --target ${{ matrix.target }}
targets: ${{ matrix.target }}
- run: cargo install cross --git https://github.com/cross-rs/cross
- run: cross build --release --target ${{ matrix.target }}

- name: zip artifact
run: zip -j godata_server-${{ matrix.target }}.zip target/${{ matrix.target }}/release/godata_server
- uses: actions/upload-artifact@v3
- uses: actions/upload-artifact@v4
with:
name: godata_server-${{ matrix.target }}
path: godata_server-${{ matrix.target }}.zip

mac_build_server:
name: Build server on macOS
runs-on: macos-latest
Expand All @@ -54,22 +52,16 @@ jobs:
matrix:
target: [x86_64-apple-darwin, aarch64-apple-darwin]
steps:
- uses: actions/checkout@v3
- uses: actions-rs/toolchain@v1
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
toolchain: stable
target: ${{ matrix.target }}
override: true
- id: build
uses: actions-rs/cargo@v1
with:
use-cross: true
command: build
args: --release --target ${{ matrix.target }}
targets: ${{ matrix.target }}
- run: cargo build --release --target ${{ matrix.target }}
- name: zip artifact
run: zip -j godata_server-${{ matrix.target }}.zip target/${{ matrix.target }}/release/godata_server

- uses: actions/upload-artifact@v3
- uses: actions/upload-artifact@v4
with:
name: godata_server-${{ matrix.target }}
path: godata_server-${{ matrix.target }}.zip
Expand All @@ -85,15 +77,15 @@ jobs:
target: [x86_64-unknown-linux-gnu]
python-version: ["3.10", "3.11", "3.12"]
steps:
- uses: actions/checkout@v3
- uses: actions/download-artifact@v3
- uses: actions/checkout@v4
- uses: actions/download-artifact@v4
with:
name: godata_server-${{ matrix.target }}
path: server
- name: unzip artifact
run: unzip -j server/godata_server-${{ matrix.target }}.zip -d server
- name: install python
uses: actions/setup-python@v2
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install Poetry
Expand Down Expand Up @@ -122,16 +114,16 @@ jobs:
target: [x86_64-apple-darwin]
python-version: ["3.10", "3.11", "3.12"]
steps:
- uses: actions/checkout@v3
- uses: actions/download-artifact@v3
- uses: actions/checkout@v4
- uses: actions/download-artifact@v4
with:
name: godata_server-${{ matrix.target }}
path: server
- name: unzip artifact
run: unzip -j server/godata_server-${{ matrix.target }}.zip -d server

- name: install python
uses: actions/setup-python@v2
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install Poetry
Expand All @@ -154,7 +146,7 @@ jobs:
outputs:
tag: ${{ steps.get_tag.outputs.tag }}
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: get commit tag
id: get_tag
uses: olegtarasov/get-tag@v2.1.2
Expand Down Expand Up @@ -204,7 +196,7 @@ jobs:
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/')
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: build and publish to pypi
uses: JRubics/poetry-publish@v1.17
with:
Expand All @@ -222,7 +214,7 @@ jobs:
- name: "Build Changelog"
id: build_changelog
uses: mikepenz/release-changelog-builder-action@v4.1.1
- uses: actions/download-artifact@v3
- uses: actions/download-artifact@v4
- uses: ncipollo/release-action@v1.13.0
with:
token: ${{ secrets.RELEASE_TOKEN }}
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ serde = {version = "1.0.188", features = ["derive"]}
serde_json = "1.0.106"
sled = "0.34.7"
sysinfo = "0.30.5"
tokio = {features = ["full"]}
tokio = {version = "1.36.0", features = ["full"]}
tokio-stream = { version = "0.1.14", features = ["net"] }
uuid = { version = "1.5.0", features = ["v4"] }
warp = "0.3.6"
Expand Down
7 changes: 3 additions & 4 deletions godata/cli/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,10 @@ def stop():
"-p",
help="Path to install the server binary.",
type=click.Path(file_okay=False, resolve_path=True, path_type=Path),
default=srv.get_server_location(),
)
def install(upgrade: bool, path: Path):
print(f"Installing server at {path}")
srv.set_server_location(path)
def install(upgrade: bool, path: Path = None):
if path is not None:
srv.set_server_location(path)
if upgrade:
srv.upgrade()
else:
Expand Down
10 changes: 5 additions & 5 deletions godata/client/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,8 @@ def check_server(client, url):

@cache
def get_client():
try:
with open(Path.home() / ".godata_server", "r") as f:
SERVER_URL = f.read().strip()
except FileNotFoundError:
SERVER_URL = None
server_config = server.get_config()
SERVER_URL = server_config.server_url

if not SERVER_URL:
server.start()
Expand Down Expand Up @@ -169,6 +166,9 @@ def drop_project(collection_name: str, project_name: str):
return {}
if resp.status_code == 200:
return resp.json()
elif resp.status_code == 404:
# Project is not loaded, so we don't care
return {}
else:
raise GodataClientError(f"{resp.status_code}: {resp.text}")

Expand Down
93 changes: 4 additions & 89 deletions godata/server/__init__.py
Original file line number Diff line number Diff line change
@@ -1,90 +1,5 @@
import os
import pickle
import signal
import subprocess
import time
from functools import cache
from pathlib import Path
from urllib import parse
from .cmd import set_server_location, start, stop
from .config import get_config
from .install import install, upgrade

import appdirs

from .install import DEFAULT_SERVER_INSTALL_LOCATION, install, upgrade


@cache
def get_server_path():
config_path = Path(appdirs.user_config_dir("godata")) / "server_path"
if not config_path.exists():
return DEFAULT_SERVER_INSTALL_LOCATION / "godata_server"

with open(config_path, "rb") as f:
return pickle.load(f)


@cache
def get_server_location():
full_path = get_server_path()
return full_path.parent


def set_server_location(path: Path):
server_path = path / "godata_server"
config_path = Path(appdirs.user_config_dir("godata"))
config_path.mkdir(parents=True, exist_ok=True)
path_path = config_path / "server_path"
with open(path_path, "wb") as f:
pickle.dump(server_path, f)


def start(port: int = None):
# check if a godata_server process is already running

try:
server_pid = subprocess.check_output(["pgrep", "godata_server"])
print(
f"Server is already running with PID {int(server_pid)}. "
"Please stop the server before starting a new one."
)
return
except subprocess.CalledProcessError:
pass

try:
command = str(get_server_path())
if port:
command += f" --port={port}"
url = f"http://localhost:{port}"
else:
SERVER_PATH = str(Path.home() / ".godata.sock")
url = f"http+unix://{parse.quote(SERVER_PATH, safe='')}"
FILE_OUTPUT_PATH = Path.home() / ".godata_server"
with open(FILE_OUTPUT_PATH, "w") as f:
f.write(url)
subprocess.Popen(command, close_fds=True, shell=True)
except FileNotFoundError:
raise FileNotFoundError(
"Unable to start godata server: could not find the server binary. "
"Please run `godata server install` first."
)
time.sleep(0.5)
return True


def stop():
try:
server_pid = subprocess.check_output(["pgrep", "godata_server"])
except subprocess.CalledProcessError:
print("Server is not running.")
return
# kill the server
print(int(server_pid))
os.kill(int(server_pid), signal.SIGINT)
# remove the file that stores the server url
print("STOPPED")
FILE_OUTPUT_PATH = Path.home() / ".godata_server"
if FILE_OUTPUT_PATH.exists():
FILE_OUTPUT_PATH.unlink()


__all__ = ["start", "stop", "install", "upgrade"]
__all__ = ["start", "stop", "install", "upgrade", "get_config", "set_server_location"]
84 changes: 84 additions & 0 deletions godata/server/cmd.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import json
import os
import signal
import subprocess
import time
from pathlib import Path
from urllib import parse

import portalocker

from .config import SERVER_CONFIG_PATH, ServerConfig


def set_server_location(path: Path):
if not path.is_dir():
raise ValueError(f"{path} is not a valid directory.")
binary_path = path / "godata_server"

with portalocker.Lock(SERVER_CONFIG_PATH, "r+") as f:
config = json.load(f)
config = ServerConfig(**config)
if config.is_running:
raise RuntimeError("Cannot change server path while server is running")
config.server_path = binary_path
# clear the file contents
f.seek(0)
f.truncate()
f.write(config.model_dump_json(indent=2))


def start(port: int = None):
# check if a godata_server process is already running
with portalocker.Lock(SERVER_CONFIG_PATH, "r+") as f:
config = json.load(f)
config = ServerConfig(**config)
already_running = config.is_running

if not already_running:
config.is_running = True
config.port = port

try:
command = str(config.server_path)
if port:
command += f" --port={port}"
url = f"http://localhost:{port}"
else:
SERVER_PATH = str(Path.home() / ".godata.sock")
url = f"http+unix://{parse.quote(SERVER_PATH, safe='')}"

config.server_url = url
subprocess.Popen(command, close_fds=True, shell=True)
except FileNotFoundError:
raise FileNotFoundError(
"Unable to start godata server: could not find the server binary. "
"Please run `godata server install` first."
)
f.seek(0)
f.truncate()
f.write(config.model_dump_json(indent=2))
time.sleep(0.1)

return not already_running


def stop():
with portalocker.Lock(SERVER_CONFIG_PATH, "r+") as f:
config = json.load(f)
config = ServerConfig(**config)
if not config.is_running:
raise RuntimeError("Server is not running.")

# check if the url is a unix socket or localhost
local_urls = ["http://localhost", "http+unix://"]
if not any(config.server_url.startswith(url) for url in local_urls):
raise RuntimeError("Cannot stop server running on a remote host.")

server_pid = subprocess.check_output(["pgrep", "godata_server"])
os.kill(int(server_pid), signal.SIGINT)

config.stop()
f.seek(0)
f.truncate()
f.write(config.model_dump_json(indent=2))
Loading

0 comments on commit 266abff

Please sign in to comment.