github.com/0chain/gosdk@v1.17.11/wasmsdk/cache.go (about)

     1  //go:build js && wasm
     2  // +build js,wasm
     3  
     4  package main
     5  
     6  import (
     7  	"context"
     8  	"errors"
     9  	"time"
    10  
    11  	"github.com/0chain/gosdk/wasmsdk/jsbridge"
    12  	"github.com/0chain/gosdk/zboxcore/client"
    13  	"github.com/0chain/gosdk/zboxcore/sdk"
    14  	lru "github.com/hashicorp/golang-lru/v2"
    15  )
    16  
    17  type cachedAllocation struct {
    18  	Expiration time.Time
    19  	Allocation *sdk.Allocation
    20  }
    21  
    22  var (
    23  	cachedAllocations, _ = lru.New[string, *cachedAllocation](100)
    24  )
    25  
    26  // getAllocation get allocation from cache
    27  // if not found in cache, fetch from blockchain
    28  // and store in cache
    29  //   - allocationId is the allocation id
    30  func getAllocation(allocationId string) (*sdk.Allocation, error) {
    31  
    32  	it, ok := cachedAllocations.Get(allocationId)
    33  
    34  	if ok {
    35  		if ok && it.Expiration.After(time.Now()) {
    36  			return it.Allocation, nil
    37  		}
    38  	}
    39  	sdk.SetWasm()
    40  	a, err := sdk.GetAllocation(allocationId)
    41  	if err != nil {
    42  		return nil, err
    43  	}
    44  	sdk.SetShouldVerifyHash(false)
    45  	it = &cachedAllocation{
    46  		Allocation: a,
    47  		Expiration: time.Now().Add(120 * time.Minute),
    48  	}
    49  
    50  	cachedAllocations.Add(allocationId, it)
    51  	return it.Allocation, nil
    52  }
    53  
    54  // clearAllocation remove allocation from caching
    55  func clearAllocation(allocationID string) {
    56  	cachedAllocations.Remove(allocationID)
    57  }
    58  
    59  // reloadAllocation reload allocation from blockchain and update cache
    60  //   - allocationID is the allocation id
    61  func reloadAllocation(allocationID string) (*sdk.Allocation, error) {
    62  	a, err := sdk.GetAllocation(allocationID)
    63  	if err != nil {
    64  		return nil, err
    65  	}
    66  
    67  	it := &cachedAllocation{
    68  		Allocation: a,
    69  		Expiration: time.Now().Add(5 * time.Minute),
    70  	}
    71  
    72  	cachedAllocations.Add(allocationID, it)
    73  
    74  	return it.Allocation, nil
    75  }
    76  
    77  func addWebWorkers(alloc *sdk.Allocation) (err error) {
    78  	c := client.GetClient()
    79  	if c == nil || len(c.Keys) == 0 {
    80  		return
    81  	}
    82  	ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
    83  	defer cancel()
    84  	respChan := make(chan error, len(alloc.Blobbers))
    85  	respRequired := 0
    86  	for _, blober := range alloc.Blobbers {
    87  		weborker, workerCreated, _ := jsbridge.NewWasmWebWorker(blober.ID,
    88  			blober.Baseurl,
    89  			c.ClientID,
    90  			c.ClientKey,
    91  			c.PeerPublicKey,
    92  			c.Keys[0].PublicKey,
    93  			c.Keys[0].PrivateKey,
    94  			c.Mnemonic,
    95  			c.IsSplit) //nolint:errcheck
    96  		if workerCreated {
    97  			respRequired++
    98  			go func() {
    99  				eventChan, err := weborker.Listen(ctx)
   100  				if err != nil {
   101  					respChan <- err
   102  					return
   103  				}
   104  				_, ok := <-eventChan
   105  				if !ok {
   106  					respChan <- errors.New("worker chan closed")
   107  					return
   108  				}
   109  				respChan <- nil
   110  			}()
   111  		}
   112  	}
   113  	if respRequired == 0 {
   114  		return
   115  	}
   116  	for {
   117  		select {
   118  		case <-ctx.Done():
   119  			PrintError(ctx.Err())
   120  			return ctx.Err()
   121  		case err = <-respChan:
   122  			if err != nil {
   123  				PrintError(err)
   124  				return
   125  			}
   126  			respRequired--
   127  			if respRequired == 0 {
   128  				close(respChan)
   129  				return
   130  			}
   131  		}
   132  	}
   133  }