start work to fall back to full computation when the incremental change is too big
1 files changed, 56 insertions(+), 10 deletions(-)

M wispwot/wispwot.w
M wispwot/wispwot.w +56 -10
@@ 309,7 309,11 @@ define : update-ranks-from-trustee! wots
   This is an incremental update.
   
   Returns '((index old-rank new-rank) ...) for all indexes of ids
-  whose *capacity* was changed in the trustlists due to the update."
+  whose *capacity* was changed in the trustlists due to the update.
+  
+  If too many IDs change, returns #f. Use via
+  (or (and=> (update-ranks-from-trustee! ...) (cut update-scores-from-changed-ranks! wotstate <>))
+      (... (calculate-ranks ...) ...))"
   ;; when I gain rank, only the trustees of the trustee are relevant.
   
   ;; when I lose trust, any ID with rank equal or lower than the

          
@@ 384,6 388,8 @@ define : update-ranks-from-trustee! wots
           ; . trustlists
   
   define known-id-len  : vector-length : wotstate-known-ids wotstate
+  ;; if more than 10% of ids change, fallback to full rank and trust computation
+  define max-changed-id-count : max 100 : truncate/ known-id-len 10
   define ranks : wotstate-ranks wotstate
   define seen-ranks : make-ranks known-id-len ranks--inf
   define old-trustee-rank

          
@@ 404,6 410,9 @@ define : update-ranks-from-trustee! wots
             : and (null? open) (null? next)
               set-wotstate-ranks! wotstate ranks
               . changed
+            ;; return #f if too many 
+            {(length changed) > max-changed-id-count}
+              . #f
             : null? open
               ;; one level deeper
               loop (reverse! next) '() (min ranks--inf (+ rank 1)) changed

          
@@ 424,8 433,10 @@ define : update-ranks-from-trustee! wots
                     ;; FIXME: here I force a GC, because once objects get too large the GC does not trigger reliably anymore
                     when : = 0 : random 10000
                         gc
-                    if : null? trustee-indexes-in-trustlist
+                    cond
+                     : null? trustee-indexes-in-trustlist
                        reverse changed
+                     else  
                        let : : trustee-idx-in-trustlist : car trustee-indexes-in-trustlist
                           define trustee-index-local
                               ids-ref trustees trustee-idx-in-trustlist

          
@@ 1010,20 1021,55 @@ define : import-trust-value wotstate own
       set-wotstate-trustlists! state
         vector-append! : wotstate-trustlists state
           cons (list->ids (list)) (list->trusts (list))
-  ;; update changed ranks, keep list with nodes whose rank changed
-  define id-indexes-with-changed-ranks
-    update-ranks-from-trustee! state truster-rank ownid-index truster-index trustee-index
-  define trustee-score-change
-      update-score! state truster-index truster-rank truster-rank trustee-index old-trust value
-  define changed-scores
-       cons trustee-score-change
-            update-scores-from-changed-ranks! state id-indexes-with-changed-ranks
   define : replace-indizes-by-ids truster-index trustee-index old-score new-score
       define ids : wotstate-known-ids state
       list
           and=> truster-index : cut vector-ref ids <>
           vector-ref ids trustee-index
           . old-score new-score
+  ;; update changed ranks, keep list with nodes whose rank changed
+  define changed-scores-rest
+      and=> : update-ranks-from-trustee! state truster-rank ownid-index truster-index trustee-index
+              cut update-scores-from-changed-ranks! state <>
+  define changed-score-trustee
+      update-score! state truster-index truster-rank truster-rank trustee-index old-trust value
+  define changed-scores
+     if changed-scores-rest
+       cons changed-score-trustee changed-scores-rest
+       let*
+         : old-scores : wotstate-scores : add-wotstate-ranks-and-scores wotstate ownid-index
+           ranks : calculate-ranks state ownid-index
+           _ : set-wotstate-ranks! state ranks
+           scores : calculate-scores state ownid-index
+           new-ref : cut vector-ref scores <>
+           old-ref : cut vector-ref old-scores <>
+         set-wotstate-scores! state scores
+         let loop : (changed '()) (index (vector-length scores))
+             cond
+               : zero? index
+                 . changed
+               : and {index >= (vector-length old-scores)} (new-ref {index - 1})
+                 loop
+                   cons
+                     list #f ;; truster unknown
+                       . {index - 1}
+                       . #f
+                       new-ref {index - 1}
+                     . changed
+                   - index 1
+               {index >= (vector-length old-scores)} ;; new score #f
+                 loop changed : - index 1
+               : equal? (new-ref {index - 1}) (old-ref {index - 1})
+                 loop changed : - index 1
+               else
+                 loop
+                   cons
+                     list #f ;; truster unknown
+                       . {index - 1}
+                       old-ref {index - 1}
+                       new-ref {index - 1}
+                     . changed
+                   - index 1
   define changed-scores-with-ids
       map : λ (x) : apply replace-indizes-by-ids x
           remove null? changed-scores