Skip to content

Commit ba48dea

Browse files
committed
respond to /contents POST instantly and process file fetching in background
1 parent 357acbe commit ba48dea

File tree

4 files changed

+77
-14
lines changed

4 files changed

+77
-14
lines changed
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
"""add enum value to content availability
2+
3+
Revision ID: 5314853acecf
4+
Revises: 209e2baad6e1
5+
Create Date: 2023-01-21 09:47:01.173291
6+
7+
"""
8+
from alembic import op
9+
10+
from storage.db.multitenancy import for_each_tenant_schema
11+
12+
# revision identifiers, used by Alembic.
13+
revision = "5314853acecf"
14+
down_revision = "209e2baad6e1"
15+
branch_labels = None
16+
depends_on = None
17+
18+
19+
def upgrade():
20+
op.execute("ALTER TYPE contentavailability ADD VALUE 'PENDING'")
21+
22+
23+
@for_each_tenant_schema
24+
def downgrade(schema: str):
25+
op.drop_column("contents", "availability", schema=schema)
26+
op.execute("ALTER TYPE contentavailability RENAME TO contentavailability_old")
27+
op.execute(
28+
"CREATE TYPE contentavailability "
29+
"AS ENUM('INSTANT', 'ENCRYPTED', 'ARCHIVE', 'ABSENT')"
30+
)
31+
op.execute(
32+
(
33+
f"ALTER TABLE {schema}.contents "
34+
"ALTER COLUMN availability TYPE contentavailability USING "
35+
"contentavailability::text::contentavailability"
36+
)
37+
)
38+
op.execute("DROP TYPE contentavailability_old")

storage/db/models/content.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010

1111
class ContentAvailability(str, enum.Enum):
12+
PENDING = "pending"
1213
INSTANT = "instant"
1314
ENCRYPTED = "encrypted"
1415
ARCHIVE = "archive"

storage/upload.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import io
2+
3+
import httpx
4+
5+
from storage.config import settings
6+
from storage.db.models import Content
7+
from storage.db.models.content import ContentAvailability
8+
from storage.logging import log
9+
10+
11+
async def process_data_from_origin(origin: str, content_id: int, db) -> None:
12+
log.debug(f"fetching content {content_id} {origin}")
13+
async with httpx.AsyncClient() as client:
14+
r = await client.get(origin)
15+
content_file = io.BytesIO(r.content)
16+
async with httpx.AsyncClient(
17+
base_url=settings.IPFS_HTTP_PROVIDER,
18+
) as client:
19+
response = await client.post(
20+
"/api/v0/add", files={"upload-files": content_file}
21+
)
22+
23+
content: Content = db.query(Content).filter(Content.id == content_id).first()
24+
content.ipfs_cid = response.json()["Hash"]
25+
content.availability = ContentAvailability.INSTANT
26+
db.commit()
27+
db.refresh(content)
28+
log.debug(f"fetched {content=}")

storage/web/routers/contents.py

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
1-
import io
2-
31
import httpx
4-
from fastapi import APIRouter, Depends, status
2+
from fastapi import APIRouter, BackgroundTasks, Depends, status
53
from fastapi.exceptions import HTTPException
64
from fastapi.responses import RedirectResponse, StreamingResponse
75

@@ -12,6 +10,7 @@
1210
from storage.db.session import SessionLocal
1311
from storage.logging import log
1412
from storage.schemas import content as schemas
13+
from storage.upload import process_data_from_origin
1514
from storage.web import deps
1615

1716
router = APIRouter()
@@ -65,6 +64,7 @@ async def read_contents(
6564
async def create_content(
6665
*,
6766
db: SessionLocal = Depends(deps.get_db),
67+
background_tasks: BackgroundTasks,
6868
current_user: User = Depends(deps.get_current_user),
6969
content_in: schemas.ContentCreate,
7070
):
@@ -86,24 +86,20 @@ async def create_content(
8686
f"/contents/{content_id}",
8787
status_code=status.HTTP_303_SEE_OTHER,
8888
)
89-
async with httpx.AsyncClient() as client:
90-
r = await client.get(content_in.origin)
91-
content_file = io.BytesIO(r.content)
92-
async with httpx.AsyncClient(
93-
base_url=settings.IPFS_HTTP_PROVIDER,
94-
) as client:
95-
response = await client.post(
96-
"/api/v0/add", files={"upload-files": content_file}
97-
)
89+
9890
content = Content(
9991
origin=content_in.origin,
100-
ipfs_cid=response.json()["Hash"],
101-
availability=ContentAvailability.INSTANT,
92+
availability=ContentAvailability.PENDING,
10293
owner_id=current_user.id,
10394
)
10495
db.add(content)
10596
db.commit()
10697
db.refresh(content)
98+
99+
background_tasks.add_task(
100+
process_data_from_origin, origin=content.origin, content_id=content.id, db=db
101+
)
102+
107103
return content
108104

109105

0 commit comments

Comments
 (0)