Skip to content

Commit

Permalink
Start a stream upload function
Browse files Browse the repository at this point in the history
  • Loading branch information
WardLT committed Jan 2, 2025
1 parent 727835c commit 4915fc1
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 0 deletions.
40 changes: 40 additions & 0 deletions .github/workflows/python-package.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
name: Python Package

on:
push:
pull_request:

defaults:
run:
shell: bash -el {0} # Lets conda work

jobs:
build-linux:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2
- uses: conda-incubator/setup-miniconda@v2
with:
environment-file: environment.yml
activate-environment: test
auto-activate-base: true
auto-update-conda: false
remove-profiles: true
architecture: x64
clean-patched-environment-file: true
run-post: true
use-mamba: true
miniforge-version: latest
- name: Lint with flake8
run: |
flake8 roviweb/ tests
- name: Test with pytest
run: |
pytest --cov=rovidemo tests
- name: Coveralls
run: |
pip install coveralls
coveralls --service=github
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
1 change: 1 addition & 0 deletions environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ dependencies:
- python==3.12.*
- fastapi==0.115.*
- python-duckdb
- uvicorn

# Testing
- pytest
Expand Down
54 changes: 54 additions & 0 deletions roviweb/api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
"""Define the web application"""
import logging

from fastapi import FastAPI
from fastapi.websockets import WebSocket, WebSocketDisconnect
from fastapi.middleware.cors import CORSMiddleware

app = FastAPI()

app.add_middleware(
CORSMiddleware,
allow_origins=["*"]
)

logger = logging.getLogger('app')


@app.websocket('/upload')
async def upload_data(socket: WebSocket):
"""Open a socket connection for writing data to the database
The first message into the websocket is a JSON document including the name of the dataset to write to.
.. code-block: json
"name": "module-1"
The websocket will respond if it is ready to receive data and then continue without replying to the user.
.. code-block: json
{"success": true, "message": "Preparing to receive for dataset: module-1"}
The subsequent messages are the data to be stored.
The web service will add a timestamp and then store the data as-is.
Args:
socket: The websocket created for this particular session
"""

# Accept the connection
await socket.accept()
logger.info(f'Connected to client at {socket.client.host}')

try:
# Retrieve the name of the dataset
msg = await socket.receive_json()
if 'name' not in msg:
await socket.send_json({'success': False, 'reason': 'Initial JSON message must contain a key "name"'})
name = msg['name']
await socket.send_json({'success': True, 'message': f'Preparing to receive for dataset: {name}'})

except WebSocketDisconnect:
logger.info(f'Disconnected from client at {socket.client.host}')
6 changes: 6 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[bdist_wheel]
universal = 1

[flake8]
exclude = .git,*.egg*
max-line-length = 120
16 changes: 16 additions & 0 deletions tests/test_upload.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from pytest import fixture
from fastapi.testclient import TestClient

from roviweb.api import app


@fixture()
def client():
return TestClient(app)


def test_connect(client):
with client.websocket_connect("/upload") as websocket:
websocket.send_json({"name": "module-1"})
msg = websocket.receive_json()
assert msg['success'] and msg['message'].endswith('module-1')

0 comments on commit 4915fc1

Please sign in to comment.