@@ -77,12 +77,17 @@ declareCounter portal_gossip_without_lookup,
7777 " Portal wire protocol neighborhood gossip that did not require a node lookup" ,
7878 labels = [" protocol_id" ]
7979declareCounter portal_content_cache_hits,
80- " Portal wire protocol local content lookups that hit the cache" ,
80+ " Portal wire protocol local content lookups that hit the content cache" ,
8181 labels = [" protocol_id" ]
8282declareCounter portal_content_cache_misses,
83- " Portal wire protocol local content lookups that don't hit the cache" ,
83+ " Portal wire protocol local content lookups that don't hit the content cache" ,
84+ labels = [" protocol_id" ]
85+ declareCounter portal_offer_cache_hits,
86+ " Portal wire protocol local content lookups that hit the offer cache" ,
87+ labels = [" protocol_id" ]
88+ declareCounter portal_offer_cache_misses,
89+ " Portal wire protocol local content lookups that don't hit the offer cache" ,
8490 labels = [" protocol_id" ]
85-
8691declareCounter portal_poke_offers,
8792 " Portal wire protocol offers through poke mechanism" , labels = [" protocol_id" ]
8893
141146
142147 DbStoreHandler * = proc (
143148 contentKey: ContentKeyByteList , contentId: ContentId , content: seq [byte ]
144- ) {.raises : [], gcsafe .}
149+ ): bool {.raises : [], gcsafe .}
145150
146151 DbContainsHandler * = proc (contentKey: ContentKeyByteList , contentId: ContentId ): bool {.
147152 raises : [], gcsafe
@@ -153,8 +158,16 @@ type
153158
154159 RadiusCache * = LruCache [NodeId , UInt256 ]
155160
161+ # Caches content fetched from the network during lookups.
162+ # Content outside our radius is also cached in order to improve performance
163+ # of queries which may lookup data outside our radius.
156164 ContentCache = LruCache [ContentId , seq [byte ]]
157165
166+ # Caches the content ids of the most recently received content offers.
167+ # Content is only stored in this cache if it falls within our radius and similarly
168+ # the cache is only checked if the content id is within our radius.
169+ OfferCache = LruCache [ContentId , bool ]
170+
158171 ContentKV * = object
159172 contentKey* : ContentKeyByteList
160173 content* : seq [byte ]
189202 radiusCache: RadiusCache
190203 offerQueue: AsyncQueue [OfferRequest ]
191204 offerWorkers: seq [Future [void ]]
205+ offerCache* : OfferCache
192206 pingTimings: Table [NodeId , chronos.Moment ]
193207 config* : PortalProtocolConfig
194208 pingExtensionCapabilities* : set [uint16 ]
@@ -529,6 +543,16 @@ proc handleFindContent(
529543
530544 encodeMessage (ContentMessage (contentMessageType: enrsType, enrs: enrs))
531545
546+ proc containsContent (
547+ p: PortalProtocol , contentKey: ContentKeyByteList , contentId: ContentId
548+ ): bool =
549+ if p.offerCache.contains (contentId):
550+ portal_offer_cache_hits.inc (labelValues = [$ p.protocolId])
551+ true
552+ else :
553+ portal_offer_cache_misses.inc (labelValues = [$ p.protocolId])
554+ p.dbContains (contentKey, contentId)
555+
532556proc handleOffer (
533557 p: PortalProtocol , o: OfferMessage , srcId: NodeId
534558): Result [AcceptMessage , string ] =
@@ -571,7 +595,7 @@ proc handleOffer(
571595 discard contentKeysAcceptList.add (DeclinedNotWithinRadius )
572596 elif not p.stream.canAddPendingTransfer (srcId, contentId):
573597 discard contentKeysAcceptList.add (DeclinedInboundTransferInProgress )
574- elif p.dbContains (contentKey, contentId):
598+ elif p.containsContent (contentKey, contentId):
575599 discard contentKeysAcceptList.add (DeclinedAlreadyStored )
576600 else :
577601 p.stream.addPendingTransfer (srcId, contentId)
@@ -712,6 +736,8 @@ proc new*(
712736 stream: stream,
713737 radiusCache: RadiusCache .init (256 ),
714738 offerQueue: newAsyncQueue [OfferRequest ](config.maxConcurrentOffers),
739+ offerCache:
740+ OfferCache .init (if config.disableOfferCache: 0 else : config.offerCacheSize),
715741 pingTimings: Table [NodeId , chronos.Moment ](),
716742 config: config,
717743 pingExtensionCapabilities: pingExtensionCapabilities,
@@ -1133,6 +1159,7 @@ proc offer(
11331159 return err (" Error writing requested data" )
11341160
11351161 trace " Offered content item send" , dataWritten = dataWritten
1162+
11361163 await socket.closeWait ()
11371164 trace " Content successfully offered"
11381165
@@ -1789,6 +1816,7 @@ proc storeContent*(
17891816 contentId: ContentId ,
17901817 content: seq [byte ],
17911818 cacheContent = false ,
1819+ cacheOffer = false ,
17921820): bool {.discardable .} =
17931821 if cacheContent and not p.config.disableContentCache:
17941822 # We cache content regardless of whether it is in our radius or not
@@ -1797,8 +1825,15 @@ proc storeContent*(
17971825 # Always re-check that the key is still in the node range to make sure only
17981826 # content in range is stored.
17991827 if p.inRange (contentId):
1800- doAssert (p.dbPut != nil )
1801- p.dbPut (contentKey, contentId, content)
1828+ let dbPruned = p.dbPut (contentKey, contentId, content)
1829+ if dbPruned:
1830+ # invalidate all cached content incase it was removed from the database
1831+ # during pruning
1832+ p.offerCache = OfferCache .init (p.offerCache.capacity)
1833+
1834+ if cacheOffer and not p.config.disableOfferCache:
1835+ p.offerCache.put (contentId, true )
1836+
18021837 true
18031838 else :
18041839 false
0 commit comments