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

Better Server Settings Management #13

Merged
merged 10 commits into from
Feb 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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