Make IPFS pinning non-blocking (fire-and-forget)
IPFS pinning can take a long time if content needs to be fetched from the network. Changed all pin operations to run in background threads so they don't block the HTTP response. This fixes the 30s timeout issue when publishing assets. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
41
server.py
41
server.py
@@ -1599,13 +1599,9 @@ async def update_asset(name: str, req: UpdateAssetRequest, user: User = Depends(
|
||||
updates["origin"] = req.origin
|
||||
if req.ipfs_cid is not None:
|
||||
updates["ipfs_cid"] = req.ipfs_cid
|
||||
# Pin on IPFS
|
||||
try:
|
||||
import ipfs_client
|
||||
if ipfs_client.is_available():
|
||||
ipfs_client.pin(req.ipfs_cid)
|
||||
except Exception as e:
|
||||
logger.warning(f"Failed to pin IPFS content {req.ipfs_cid}: {e}")
|
||||
# Pin on IPFS (fire-and-forget, don't block)
|
||||
import threading
|
||||
threading.Thread(target=_pin_ipfs_async, args=(req.ipfs_cid,), daemon=True).start()
|
||||
|
||||
# Update asset in database
|
||||
updated_asset = await db.update_asset(name, updates)
|
||||
@@ -1639,20 +1635,27 @@ async def update_asset(name: str, req: UpdateAssetRequest, user: User = Depends(
|
||||
return {"asset": updated_asset, "activity": activity}
|
||||
|
||||
|
||||
def _pin_ipfs_async(cid: str):
|
||||
"""Pin IPFS content in background thread."""
|
||||
try:
|
||||
import ipfs_client
|
||||
if ipfs_client.is_available():
|
||||
ipfs_client.pin(cid)
|
||||
logger.info(f"Pinned IPFS content: {cid}")
|
||||
except Exception as e:
|
||||
logger.warning(f"Failed to pin IPFS content {cid}: {e}")
|
||||
|
||||
|
||||
async def _register_asset_impl(req: RegisterRequest, owner: str):
|
||||
"""Internal implementation for registering an asset."""
|
||||
# Check if name exists
|
||||
if await db.asset_exists(req.name):
|
||||
raise HTTPException(400, f"Asset already exists: {req.name}")
|
||||
|
||||
# Pin content on IPFS if CID provided
|
||||
# Pin content on IPFS if CID provided (fire-and-forget, don't block)
|
||||
if req.ipfs_cid:
|
||||
try:
|
||||
import ipfs_client
|
||||
if ipfs_client.is_available():
|
||||
ipfs_client.pin(req.ipfs_cid)
|
||||
except Exception as e:
|
||||
logger.warning(f"Failed to pin IPFS content {req.ipfs_cid}: {e}")
|
||||
import threading
|
||||
threading.Thread(target=_pin_ipfs_async, args=(req.ipfs_cid,), daemon=True).start()
|
||||
|
||||
# Create asset
|
||||
now = datetime.now(timezone.utc).isoformat()
|
||||
@@ -1794,14 +1797,10 @@ async def publish_cache(req: PublishCacheRequest, user: User = Depends(get_requi
|
||||
if await db.asset_exists(req.asset_name):
|
||||
raise HTTPException(400, f"Asset name already exists: {req.asset_name}")
|
||||
|
||||
# Pin content on IPFS if CID provided
|
||||
# Pin content on IPFS if CID provided (fire-and-forget, don't block)
|
||||
if req.ipfs_cid:
|
||||
try:
|
||||
import ipfs_client
|
||||
if ipfs_client.is_available():
|
||||
ipfs_client.pin(req.ipfs_cid)
|
||||
except Exception as e:
|
||||
logger.warning(f"Failed to pin IPFS content {req.ipfs_cid}: {e}")
|
||||
import threading
|
||||
threading.Thread(target=_pin_ipfs_async, args=(req.ipfs_cid,), daemon=True).start()
|
||||
|
||||
# Create asset
|
||||
now = datetime.now(timezone.utc).isoformat()
|
||||
|
||||
Reference in New Issue
Block a user