mirror of https://github.com/skygpu/skynet.git
Create fully async ipfs client, and stop using docker on worker
parent
7f50952088
commit
01cbc736a0
|
@ -16,7 +16,7 @@ from leap.cleos import CLEOS
|
||||||
from leap.sugar import collect_stdout, Name, asset_from_str
|
from leap.sugar import collect_stdout, Name, asset_from_str
|
||||||
from leap.hyperion import HyperionAPI
|
from leap.hyperion import HyperionAPI
|
||||||
|
|
||||||
from skynet.ipfs import IPFSHTTP
|
from skynet.ipfs import AsyncIPFSHTTP
|
||||||
|
|
||||||
|
|
||||||
from .db import open_new_database
|
from .db import open_new_database
|
||||||
|
@ -516,7 +516,7 @@ def pinner(loglevel, ipfs_rpc, hyperion_url):
|
||||||
from .ipfs.pinner import SkynetPinner
|
from .ipfs.pinner import SkynetPinner
|
||||||
|
|
||||||
logging.basicConfig(level=loglevel)
|
logging.basicConfig(level=loglevel)
|
||||||
ipfs_node = IPFSHTTP(ipfs_rpc)
|
ipfs_node = AsyncIPFSHTTP(ipfs_rpc)
|
||||||
hyperion = HyperionAPI(hyperion_url)
|
hyperion = HyperionAPI(hyperion_url)
|
||||||
|
|
||||||
pinner = SkynetPinner(hyperion, ipfs_node)
|
pinner = SkynetPinner(hyperion, ipfs_node)
|
||||||
|
|
|
@ -73,7 +73,7 @@ class SkynetDGPUDaemon:
|
||||||
img_sha, img_raw = self.mm.compute_one(
|
img_sha, img_raw = self.mm.compute_one(
|
||||||
body['method'], body['params'], binary=binary)
|
body['method'], body['params'], binary=binary)
|
||||||
|
|
||||||
ipfs_hash = self.conn.publish_on_ipfs( img_raw)
|
ipfs_hash = await self.conn.publish_on_ipfs(img_raw)
|
||||||
|
|
||||||
await self.conn.submit_work(rid, request_hash, img_sha, ipfs_hash)
|
await self.conn.submit_work(rid, request_hash, img_sha, ipfs_hash)
|
||||||
break
|
break
|
||||||
|
|
|
@ -3,13 +3,13 @@
|
||||||
from functools import partial
|
from functools import partial
|
||||||
import io
|
import io
|
||||||
import json
|
import json
|
||||||
|
from pathlib import Path
|
||||||
import time
|
import time
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
import asks
|
import asks
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
|
|
||||||
from contextlib import ExitStack
|
|
||||||
from contextlib import asynccontextmanager as acm
|
from contextlib import asynccontextmanager as acm
|
||||||
|
|
||||||
from leap.cleos import CLEOS
|
from leap.cleos import CLEOS
|
||||||
|
@ -17,8 +17,7 @@ from leap.sugar import Checksum256, Name, asset_from_str
|
||||||
from skynet.constants import DEFAULT_DOMAIN
|
from skynet.constants import DEFAULT_DOMAIN
|
||||||
|
|
||||||
from skynet.dgpu.errors import DGPUComputeError
|
from skynet.dgpu.errors import DGPUComputeError
|
||||||
from skynet.ipfs import get_ipfs_file
|
from skynet.ipfs import AsyncIPFSHTTP, get_ipfs_file
|
||||||
from skynet.ipfs.docker import open_ipfs_node
|
|
||||||
|
|
||||||
|
|
||||||
async def failable(fn: partial, ret_fail=None):
|
async def failable(fn: partial, ret_fail=None):
|
||||||
|
@ -38,28 +37,17 @@ class SkynetGPUConnector:
|
||||||
self.account = Name(config['account'])
|
self.account = Name(config['account'])
|
||||||
self.permission = config['permission']
|
self.permission = config['permission']
|
||||||
self.key = config['key']
|
self.key = config['key']
|
||||||
|
|
||||||
self.node_url = config['node_url']
|
self.node_url = config['node_url']
|
||||||
self.hyperion_url = config['hyperion_url']
|
self.hyperion_url = config['hyperion_url']
|
||||||
self.ipfs_url = config['ipfs_url']
|
|
||||||
|
|
||||||
self.cleos = CLEOS(
|
self.cleos = CLEOS(
|
||||||
None, None, self.node_url, remote=self.node_url)
|
None, None, self.node_url, remote=self.node_url)
|
||||||
|
|
||||||
self._exit_stack = ExitStack()
|
self.ipfs_gateway_url = config['ipfs_gateway_url']
|
||||||
|
self.ipfs_url = config['ipfs_url']
|
||||||
def connect(self):
|
|
||||||
self.ipfs_node = self._exit_stack.enter_context(
|
|
||||||
open_ipfs_node())
|
|
||||||
|
|
||||||
def disconnect(self):
|
|
||||||
self._exit_stack.close()
|
|
||||||
|
|
||||||
@acm
|
|
||||||
async def open(self):
|
|
||||||
self.connect()
|
|
||||||
yield self
|
|
||||||
self.disconnect()
|
|
||||||
|
|
||||||
|
self.ipfs_client = AsyncIPFSHTTP(self.ipfs_url)
|
||||||
|
|
||||||
# blockchain helpers
|
# blockchain helpers
|
||||||
|
|
||||||
|
@ -206,21 +194,23 @@ class SkynetGPUConnector:
|
||||||
|
|
||||||
# IPFS helpers
|
# IPFS helpers
|
||||||
|
|
||||||
def publish_on_ipfs(self, raw_img: bytes):
|
async def publish_on_ipfs(self, raw_img: bytes):
|
||||||
logging.info('publish_on_ipfs')
|
logging.info('publish_on_ipfs')
|
||||||
img = Image.open(io.BytesIO(raw_img))
|
img = Image.open(io.BytesIO(raw_img))
|
||||||
img.save(f'ipfs-docker-staging/image.png')
|
img.save('ipfs-docker-staging/image.png')
|
||||||
|
|
||||||
# check peer connections, reconnect to skynet gateway if not
|
# check peer connections, reconnect to skynet gateway if not
|
||||||
peers = self.ipfs_node.check_connect()
|
peers = await self.ipfs_client.peers()
|
||||||
if self.ipfs_url not in peers:
|
peer_addresses = [peer['Addr'] for peer in peers]
|
||||||
self.ipfs_node.connect(self.ipfs_url)
|
if self.ipfs_gateway_url not in peer_addresses:
|
||||||
|
await self.ipfs_client.connect(self.ipfs_gateway_url)
|
||||||
|
|
||||||
ipfs_hash = self.ipfs_node.add('image.png')
|
file_info = await self.ipfs_client.add(Path('ipfs-docker-staging/image.png'))
|
||||||
|
file_cid = file_info['Hash']
|
||||||
|
|
||||||
self.ipfs_node.pin(ipfs_hash)
|
await self.ipfs_client.pin(file_cid)
|
||||||
|
|
||||||
return ipfs_hash
|
return file_cid
|
||||||
|
|
||||||
async def get_input_data(self, ipfs_hash: str) -> bytes:
|
async def get_input_data(self, ipfs_hash: str) -> bytes:
|
||||||
if ipfs_hash == '':
|
if ipfs_hash == '':
|
||||||
|
|
|
@ -1,26 +1,61 @@
|
||||||
#!/usr/bin/python
|
#!/usr/bin/python
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
import asks
|
import asks
|
||||||
import requests
|
|
||||||
|
|
||||||
|
|
||||||
class IPFSHTTP:
|
class IPFSClientException(BaseException):
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
class AsyncIPFSHTTP:
|
||||||
|
|
||||||
def __init__(self, endpoint: str):
|
def __init__(self, endpoint: str):
|
||||||
self.endpoint = endpoint
|
self.endpoint = endpoint
|
||||||
|
|
||||||
def pin(self, cid: str):
|
async def _post(self, sub_url: str, *args, **kwargs):
|
||||||
return requests.post(
|
resp = await asks.post(
|
||||||
f'{self.endpoint}/api/v0/pin/add',
|
self.endpoint + sub_url,
|
||||||
|
*args, **kwargs
|
||||||
|
)
|
||||||
|
|
||||||
|
if resp.status_code != 200:
|
||||||
|
raise IPFSClientException(resp.text)
|
||||||
|
|
||||||
|
return resp.json()
|
||||||
|
|
||||||
|
async def add(self, file_path: Path, **kwargs):
|
||||||
|
files = {
|
||||||
|
'file': (str(file_path), open(file_path, 'rb'))
|
||||||
|
}
|
||||||
|
headers = {
|
||||||
|
'Content-Type': 'multipart/form-data'
|
||||||
|
}
|
||||||
|
return await self._post(
|
||||||
|
'/api/v0/add',
|
||||||
|
files=files,
|
||||||
|
headers=headers,
|
||||||
|
params=kwargs
|
||||||
|
)
|
||||||
|
|
||||||
|
async def pin(self, cid: str):
|
||||||
|
return await self._post(
|
||||||
|
'/api/v0/pin/add',
|
||||||
params={'arg': cid}
|
params={'arg': cid}
|
||||||
)
|
)
|
||||||
|
|
||||||
async def a_pin(self, cid: str):
|
async def connect(self, multi_addr: str):
|
||||||
return await asks.post(
|
return await self._post(
|
||||||
f'{self.endpoint}/api/v0/pin/add',
|
'/api/v0/swarm/connect',
|
||||||
params={'arg': cid}
|
params={'arg': multi_addr}
|
||||||
|
)
|
||||||
|
|
||||||
|
async def peers(self, **kwargs):
|
||||||
|
return await self._post(
|
||||||
|
'/api/v0/swarm/peers',
|
||||||
|
params=kwargs
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ import trio
|
||||||
|
|
||||||
from leap.hyperion import HyperionAPI
|
from leap.hyperion import HyperionAPI
|
||||||
|
|
||||||
from . import IPFSHTTP
|
from . import AsyncIPFSHTTP
|
||||||
|
|
||||||
|
|
||||||
MAX_TIME = timedelta(seconds=20)
|
MAX_TIME = timedelta(seconds=20)
|
||||||
|
@ -20,7 +20,7 @@ class SkynetPinner:
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
hyperion: HyperionAPI,
|
hyperion: HyperionAPI,
|
||||||
ipfs_http: IPFSHTTP
|
ipfs_http: AsyncIPFSHTTP
|
||||||
):
|
):
|
||||||
self.hyperion = hyperion
|
self.hyperion = hyperion
|
||||||
self.ipfs_http = ipfs_http
|
self.ipfs_http = ipfs_http
|
||||||
|
@ -85,7 +85,7 @@ class SkynetPinner:
|
||||||
for _ in range(6):
|
for _ in range(6):
|
||||||
try:
|
try:
|
||||||
with trio.move_on_after(5):
|
with trio.move_on_after(5):
|
||||||
resp = await self.ipfs_http.a_pin(cid)
|
resp = await self.ipfs_http.pin(cid)
|
||||||
if resp.status_code != 200:
|
if resp.status_code != 200:
|
||||||
logging.error(f'error pinning {cid}:\n{resp.text}')
|
logging.error(f'error pinning {cid}:\n{resp.text}')
|
||||||
del self._pinned[cid]
|
del self._pinned[cid]
|
||||||
|
|
Loading…
Reference in New Issue