Simplify method for handle save received squeak (#1740)

* Split up and simplify save received squeak method

* Got waiting dialog for download in progress for offers

* Remove old comments from squeak controller

* Fix call increment counter when lookup returns none

* Update frontend build
This commit is contained in:
Jonathan Zernik 2021-10-28 00:01:24 -07:00 committed by GitHub
parent a8745d0dbd
commit e765d584aa
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 137 additions and 49 deletions

View file

@ -18,6 +18,8 @@ import {
import useStyles from './styles';
import BuyOfferDetailItem from '../BuyOfferDetailItem';
import DownloadInProgressDialog from '../../components/DownloadInProgressDialog';
import {
downloadOffersRequest,
@ -38,6 +40,7 @@ export default function BuySqueakDialog({
const [selectedOfferId, setSelectedOfferId] = useState('');
const [offers, setOffers] = useState([]);
const [loading, setLoading] = useState(false);
const [waitingForDownloadOffers, setWaitingForDownloadOffers] = useState(false);
const resetFields = () => {
setSelectedOfferId('');
@ -47,11 +50,6 @@ export default function BuySqueakDialog({
setSelectedOfferId(event.target.value);
};
// const payOffer = (offerID) => {
// alert('Pay offer ID here: ' + offerID);
// pay(offer.getOfferId());
// };
const loadOffers = useCallback(() => {
getBuyOffersRequest(hash, setOffers);
},
@ -60,13 +58,32 @@ export default function BuySqueakDialog({
// setOffers((prevOffers) => prevOffers.concat([offer]));
// }),
// [hash, setOffers]);
const downloadOffers = () => {
const handleDownloadOffers = () => {
console.log(`downloadOffersRequest with hash: ${hash}`);
setWaitingForDownloadOffers(true);
console.log(`downloadOffersRequest with hash: ${hash}`);
downloadOffersRequest(hash, (response) => {
// Do nothing.
setWaitingForDownloadOffers(false);
const downloadResult = response.getDownloadResult();
const numPeers = downloadResult.getNumberPeers();
const numDownloaded = downloadResult.getNumberDownloaded();
if (numPeers === 0) {
alert("Unable to download because zero connected peers.");
} else {
alert(`Downloaded ${numDownloaded} offers from ${numPeers} connected peers.`);
}
if (downloadResult.getNumberDownloaded() === 0) {
return;
}
getBuyOffersRequest(hash, setOffers);
});
};
const handleCloseOffersDownloadInProgressDialog = () => {
setWaitingForDownloadOffers(false);
};
const handlePayResponse = (response) => {
handlePaymentComplete();
setLoading(false);
@ -88,7 +105,8 @@ export default function BuySqueakDialog({
event.preventDefault();
console.log('Handling download click...');
console.log(`downloadOffersRequest with hash: ${hash}`);
downloadOffers();
// downloadOffers();
handleDownloadOffers();
};
const getSelectedOffer = () => {
@ -125,12 +143,6 @@ export default function BuySqueakDialog({
// handleClose();
}
function load(event) {
// loadOffers();
// subscribeOffers();
downloadOffers();
}
function cancel(event) {
event.stopPropagation();
handleClose();
@ -220,8 +232,20 @@ export default function BuySqueakDialog({
);
}
function OffersDownloadInProgressDialogContent() {
return (
<>
<DownloadInProgressDialog
open={waitingForDownloadOffers}
handleClose={handleCloseOffersDownloadInProgressDialog}
/>
</>
);
}
return (
<Dialog open={open} onRendered={load} onEnter={resetFields} onClose={cancel} onClick={ignore} aria-labelledby="form-dialog-title">
<>
<Dialog open={open} onEnter={resetFields} onClose={cancel} onClick={ignore} aria-labelledby="form-dialog-title">
<DialogTitle id="form-dialog-title">
Buy Squeak for hash
{hash}
@ -249,5 +273,7 @@ export default function BuySqueakDialog({
</DialogActions>
</form>
</Dialog>
{OffersDownloadInProgressDialogContent()}
</>
);
}

View file

@ -931,6 +931,8 @@ message DownloadOffersRequest {
}
message DownloadOffersReply {
// The download result
DownloadResult download_result = 1;
}
message DownloadRepliesRequest {

View file

@ -640,8 +640,12 @@ class SqueakAdminServerHandler(object):
squeak_hash = bytes.fromhex(squeak_hash_str)
logger.info(
"Handle download offer for hash: {}".format(squeak_hash_str))
self.squeak_controller.download_offers(squeak_hash)
return squeak_admin_pb2.DownloadOffersReply()
download_result = self.squeak_controller.download_offers(squeak_hash)
logger.info("Download result: {}".format(download_result))
download_result_msg = download_result_to_message(download_result)
return squeak_admin_pb2.DownloadOffersReply(
download_result=download_result_msg,
)
def handle_download_replies(self, request):
squeak_hash_str = request.squeak_hash

View file

@ -1,14 +1,14 @@
{
"files": {
"main.js": "/static/js/main.1ed3ba5e.chunk.js",
"main.js.map": "/static/js/main.1ed3ba5e.chunk.js.map",
"main.js": "/static/js/main.bf949e6a.chunk.js",
"main.js.map": "/static/js/main.bf949e6a.chunk.js.map",
"runtime-main.js": "/static/js/runtime-main.9f0ba400.js",
"runtime-main.js.map": "/static/js/runtime-main.9f0ba400.js.map",
"static/css/2.15110fae.chunk.css": "/static/css/2.15110fae.chunk.css",
"static/js/2.da272a6c.chunk.js": "/static/js/2.da272a6c.chunk.js",
"static/js/2.da272a6c.chunk.js.map": "/static/js/2.da272a6c.chunk.js.map",
"index.html": "/index.html",
"precache-manifest.26f34ad925427c0c8fca870aa9c3340f.js": "/precache-manifest.26f34ad925427c0c8fca870aa9c3340f.js",
"precache-manifest.4ae808e2f9347ef000434215b35ebe52.js": "/precache-manifest.4ae808e2f9347ef000434215b35ebe52.js",
"service-worker.js": "/service-worker.js",
"static/css/2.15110fae.chunk.css.map": "/static/css/2.15110fae.chunk.css.map",
"static/js/2.da272a6c.chunk.js.LICENSE.txt": "/static/js/2.da272a6c.chunk.js.LICENSE.txt",
@ -20,6 +20,6 @@
"static/js/runtime-main.9f0ba400.js",
"static/css/2.15110fae.chunk.css",
"static/js/2.da272a6c.chunk.js",
"static/js/main.1ed3ba5e.chunk.js"
"static/js/main.bf949e6a.chunk.js"
]
}

View file

@ -1 +1 @@
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="shortcut icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no"/><meta name="theme-color" content="#000000"/><link rel="manifest" href="/manifest.json"/><title>Squeaknode</title><meta name="description" content="Squeaknode is a frontend for accessing a squeak node"><meta name="keywords" content="squeak, bitcoin, lightning"><meta name="author" content="Flatlogic LLC."><link href="/static/css/2.15110fae.chunk.css" rel="stylesheet"></head><body style="font-family:Roboto,sans-serif"><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div><script>!function(e){function r(r){for(var n,f,l=r[0],a=r[1],i=r[2],c=0,s=[];c<l.length;c++)f=l[c],Object.prototype.hasOwnProperty.call(o,f)&&o[f]&&s.push(o[f][0]),o[f]=0;for(n in a)Object.prototype.hasOwnProperty.call(a,n)&&(e[n]=a[n]);for(p&&p(r);s.length;)s.shift()();return u.push.apply(u,i||[]),t()}function t(){for(var e,r=0;r<u.length;r++){for(var t=u[r],n=!0,l=1;l<t.length;l++){var a=t[l];0!==o[a]&&(n=!1)}n&&(u.splice(r--,1),e=f(f.s=t[0]))}return e}var n={},o={1:0},u=[];function f(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,f),t.l=!0,t.exports}f.m=e,f.c=n,f.d=function(e,r,t){f.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},f.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},f.t=function(e,r){if(1&r&&(e=f(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(f.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)f.d(t,n,function(r){return e[r]}.bind(null,n));return t},f.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return f.d(r,"a",r),r},f.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},f.p="/";var l=this["webpackJsonpsqueak-node-frontend"]=this["webpackJsonpsqueak-node-frontend"]||[],a=l.push.bind(l);l.push=r,l=l.slice();for(var i=0;i<l.length;i++)r(l[i]);var p=a;t()}([])</script><script src="/static/js/2.da272a6c.chunk.js"></script><script src="/static/js/main.1ed3ba5e.chunk.js"></script></body></html>
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="shortcut icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no"/><meta name="theme-color" content="#000000"/><link rel="manifest" href="/manifest.json"/><title>Squeaknode</title><meta name="description" content="Squeaknode is a frontend for accessing a squeak node"><meta name="keywords" content="squeak, bitcoin, lightning"><meta name="author" content="Flatlogic LLC."><link href="/static/css/2.15110fae.chunk.css" rel="stylesheet"></head><body style="font-family:Roboto,sans-serif"><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div><script>!function(e){function r(r){for(var n,f,l=r[0],a=r[1],i=r[2],c=0,s=[];c<l.length;c++)f=l[c],Object.prototype.hasOwnProperty.call(o,f)&&o[f]&&s.push(o[f][0]),o[f]=0;for(n in a)Object.prototype.hasOwnProperty.call(a,n)&&(e[n]=a[n]);for(p&&p(r);s.length;)s.shift()();return u.push.apply(u,i||[]),t()}function t(){for(var e,r=0;r<u.length;r++){for(var t=u[r],n=!0,l=1;l<t.length;l++){var a=t[l];0!==o[a]&&(n=!1)}n&&(u.splice(r--,1),e=f(f.s=t[0]))}return e}var n={},o={1:0},u=[];function f(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,f),t.l=!0,t.exports}f.m=e,f.c=n,f.d=function(e,r,t){f.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},f.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},f.t=function(e,r){if(1&r&&(e=f(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(f.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)f.d(t,n,function(r){return e[r]}.bind(null,n));return t},f.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return f.d(r,"a",r),r},f.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},f.p="/";var l=this["webpackJsonpsqueak-node-frontend"]=this["webpackJsonpsqueak-node-frontend"]||[],a=l.push.bind(l);l.push=r,l=l.slice();for(var i=0;i<l.length;i++)r(l[i]);var p=a;t()}([])</script><script src="/static/js/2.da272a6c.chunk.js"></script><script src="/static/js/main.bf949e6a.chunk.js"></script></body></html>

View file

@ -1,6 +1,6 @@
self.__precacheManifest = (self.__precacheManifest || []).concat([
{
"revision": "659b391ba9822772f21edaf86dd8ebdf",
"revision": "6cf90ea3d4880cda4ac282280529392d",
"url": "/index.html"
},
{
@ -16,8 +16,8 @@ self.__precacheManifest = (self.__precacheManifest || []).concat([
"url": "/static/js/2.da272a6c.chunk.js.LICENSE.txt"
},
{
"revision": "5d7be1d1053224a85ee6",
"url": "/static/js/main.1ed3ba5e.chunk.js"
"revision": "3f814dc318eab7a746cd",
"url": "/static/js/main.bf949e6a.chunk.js"
},
{
"revision": "cc9816de5a8639d377ea",

View file

@ -14,7 +14,7 @@
importScripts("https://storage.googleapis.com/workbox-cdn/releases/4.3.1/workbox-sw.js");
importScripts(
"/precache-manifest.26f34ad925427c0c8fca870aa9c3340f.js"
"/precache-manifest.4ae808e2f9347ef000434215b35ebe52.js"
);
self.addEventListener('message', (event) => {

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -29,6 +29,7 @@ from concurrent.futures import ThreadPoolExecutor
from concurrent.futures import TimeoutError
from typing import Dict
from typing import Optional
from typing import Union
from squeak.core import CSqueak
from squeak.messages import msg_getdata
@ -40,6 +41,7 @@ from squeak.net import CSqueakLocator
from squeaknode.core.download_result import DownloadResult
from squeaknode.core.interests import squeak_matches_interest
from squeaknode.core.offer import Offer
from squeaknode.core.squeaks import get_hash
logger = logging.getLogger(__name__)
@ -59,7 +61,7 @@ class ActiveDownload(ABC):
self.start_time_ms: Optional[int] = None
@abstractmethod
def is_interested(self, squeak: CSqueak) -> bool:
def is_interested(self, downloaded_object: Union[CSqueak, Offer]) -> bool:
"""Return True if the given squeak matches the download interest."""
@abstractmethod
@ -109,8 +111,10 @@ class InterestDownload(ActiveDownload):
self.interest = interest
super().__init__(limit)
def is_interested(self, squeak: CSqueak) -> bool:
return squeak_matches_interest(squeak, self.interest)
def is_interested(self, downloaded_object: Union[CSqueak, Offer]) -> bool:
if type(downloaded_object) is not CSqueak:
return False
return squeak_matches_interest(downloaded_object, self.interest)
def get_download_msg(self) -> MsgSerializable:
locator = CSqueakLocator(
@ -127,8 +131,10 @@ class HashDownload(ActiveDownload):
self.squeak_hash = squeak_hash
super().__init__(1)
def is_interested(self, squeak: CSqueak) -> bool:
return self.squeak_hash == get_hash(squeak)
def is_interested(self, downloaded_object: Union[CSqueak, Offer]) -> bool:
if type(downloaded_object) is not CSqueak:
return False
return self.squeak_hash == get_hash(downloaded_object)
def get_download_msg(self) -> MsgSerializable:
invs = [
@ -139,6 +145,24 @@ class HashDownload(ActiveDownload):
)
class OffersDownload(ActiveDownload):
def __init__(self, limit: int, squeak_hash: bytes):
self.squeak_hash = squeak_hash
super().__init__(limit)
def is_interested(self, downloaded_object: Union[CSqueak, Offer]) -> bool:
if type(downloaded_object) is not Offer:
return False
return downloaded_object.squeak_hash == self.squeak_hash
def get_download_msg(self) -> MsgSerializable:
invs = [
CInv(type=2, hash=self.squeak_hash)
]
return msg_getdata(inv=invs)
class ActiveDownloadManager:
def __init__(self):
@ -158,9 +182,9 @@ class ActiveDownloadManager:
self.executor.shutdown(wait=True)
logger.info("Stopped Download Manager.")
def lookup_counter(self, squeak: CSqueak) -> Optional[ActiveDownload]:
def lookup_counter(self, downloaded_object: Union[CSqueak, Offer]) -> Optional[ActiveDownload]:
for name, interest in self.downloads.items():
if interest.is_interested(squeak):
if interest.is_interested(downloaded_object):
return interest
return None
@ -187,3 +211,7 @@ class ActiveDownloadManager:
def download_hash(self, squeak_hash: bytes) -> DownloadResult:
download = HashDownload(squeak_hash)
return self.run_download(download)
def download_offers(self, limit: int, squeak_hash: bytes) -> DownloadResult:
download = OffersDownload(limit, squeak_hash)
return self.run_download(download)

View file

@ -63,8 +63,6 @@ from squeaknode.core.update_subscriptions_event import UpdateSubscriptionsEvent
from squeaknode.node.active_download_manager import ActiveDownload
from squeaknode.node.listener_subscription_client import EventListener
from squeaknode.node.received_payments_subscription_client import ReceivedPaymentsSubscriptionClient
# from squeaknode.node.temporary_interest_manager import TemporaryInterest
# from squeaknode.node.temporary_interest_manager import TemporaryInterestManager
logger = logging.getLogger(__name__)
@ -155,17 +153,38 @@ class SqueakController:
self.squeak_db.delete_squeak(squeak_hash)
def save_received_squeak(self, squeak: CSqueak) -> None:
saved_squeak_hash = None
# Try saving squeak as active download
saved_squeak_hash = self.save_active_download_squeak(squeak)
if saved_squeak_hash is None:
saved_squeak_hash = self.save_followed_squeak(squeak)
if saved_squeak_hash is not None:
self.request_offers(saved_squeak_hash)
def save_active_download_squeak(self, squeak: CSqueak) -> Optional[bytes]:
"""Save the given squeak as a result of an active download.
Returns:
bytes: the hash of the saved squeak.
"""
counter = self.get_temporary_interest_counter(squeak)
if counter:
saved_squeak_hash = self.save_squeak(squeak)
if saved_squeak_hash:
counter.increment()
elif self.squeak_matches_interest(squeak):
saved_squeak_hash = self.save_squeak(squeak)
# Download offers for the new squeak
if saved_squeak_hash:
self.download_offers(saved_squeak_hash)
if counter is None:
return None
saved_squeak_hash = self.save_squeak(squeak)
if saved_squeak_hash is None:
return None
counter.increment()
return saved_squeak_hash
def save_followed_squeak(self, squeak: CSqueak) -> Optional[bytes]:
"""Save the given squeak because it matches the followed
interest criteria.
Returns:
bytes: the hash of the saved squeak.
"""
if not self.squeak_matches_interest(squeak):
return None
return self.save_squeak(squeak)
def squeak_matches_interest(self, squeak: CSqueak) -> bool:
locator = self.get_interested_locator()
@ -553,6 +572,9 @@ class SqueakController:
if received_offer_id is None:
return
logger.info("Saved received offer: {}".format(received_offer))
counter = self.active_download_manager.lookup_counter(offer)
if counter is not None:
counter.increment()
received_offer = received_offer._replace(
received_offer_id=received_offer_id)
self.new_received_offer_listener.handle_new_item(received_offer)
@ -709,10 +731,16 @@ class SqueakController:
))
return self.active_download_manager.download_hash(squeak_hash)
def download_offers(self, squeak_hash: bytes):
def download_offers(self, squeak_hash: bytes) -> DownloadResult:
logger.info("Downloading offers for squeak: {}".format(
squeak_hash.hex(),
))
return self.active_download_manager.download_offers(10, squeak_hash)
def request_offers(self, squeak_hash: bytes):
logger.info("Requesting offers for squeak: {}".format(
squeak_hash.hex(),
))
invs = [
CInv(type=2, hash=squeak_hash)
]