github.com/web-platform-tests/wpt.fyi@v0.0.0-20240530210107-70cf978996f1/api/metadata_cache.go (about)

     1  // Copyright 2020 The WPT Dashboard Project. All rights reserved.
     2  // Use of this source code is governed by a BSD-style license that can be
     3  // found in the LICENSE file.
     4  
     5  package api
     6  
     7  import (
     8  	"context"
     9  	"errors"
    10  	"net/http"
    11  	"time"
    12  
    13  	"github.com/google/go-github/v47/github"
    14  	"github.com/web-platform-tests/wpt.fyi/shared"
    15  )
    16  
    17  const metadataCacheKey = "WPT-METADATA"
    18  const metadataCacheExpiry = time.Minute * 10
    19  
    20  type webappMetadataFetcher struct {
    21  	ctx          context.Context // nolint:containedctx // TODO: Fix containedctx lint error
    22  	httpClient   *http.Client
    23  	gitHubClient *github.Client
    24  	forceUpdate  bool
    25  }
    26  
    27  func (f webappMetadataFetcher) Fetch() (sha *string, res map[string][]byte, err error) {
    28  	log := shared.GetLogger(f.ctx)
    29  	mCache := shared.NewJSONObjectCache(f.ctx, shared.NewRedisReadWritable(f.ctx, metadataCacheExpiry))
    30  	if !f.forceUpdate {
    31  		sha, metadataMap, err := getMetadataFromRedis(mCache)
    32  		if err == nil {
    33  			return sha, metadataMap, nil
    34  		}
    35  		log.Debugf("Metadata cache missed: %v", err)
    36  	}
    37  
    38  	sha, err = shared.GetWPTMetadataMasterSHA(f.ctx, f.gitHubClient)
    39  	if err != nil {
    40  		log.Errorf("Error getting HEAD SHA of wpt-metadata: %v", err)
    41  
    42  		return nil, nil, err
    43  	}
    44  
    45  	res, err = shared.GetWPTMetadataArchive(f.httpClient, sha)
    46  	if err != nil {
    47  		log.Errorf("Error getting archive of wpt-metadata: %v", err)
    48  
    49  		return nil, nil, err
    50  	}
    51  
    52  	if err := fillMetadataToRedis(mCache, *sha, res); err != nil {
    53  		// This is not a fatal failure.
    54  		log.Errorf("Error storing metadata to cache: %v", err)
    55  	}
    56  
    57  	return sha, res, nil
    58  }
    59  
    60  func getMetadataFromRedis(cache shared.ObjectCache) (sha *string, res map[string][]byte, err error) {
    61  	var metadataSHAMap map[string]map[string][]byte
    62  	err = cache.Get(metadataCacheKey, &metadataSHAMap)
    63  	if err != nil {
    64  		return nil, nil, err
    65  	}
    66  
    67  	// Caches hit; update Metadata.
    68  	keys := make([]string, 0, len(metadataSHAMap))
    69  	for key := range metadataSHAMap {
    70  		keys = append(keys, key)
    71  	}
    72  
    73  	if len(keys) != 1 {
    74  		return nil, nil, errors.New("error from getting the wpt-metadata SHA in metadataSHAMap")
    75  	}
    76  
    77  	sha = &keys[0]
    78  
    79  	return sha, metadataSHAMap[*sha], nil
    80  }
    81  
    82  func fillMetadataToRedis(cache shared.ObjectCache, sha string, metadataByteMap map[string][]byte) error {
    83  	metadataSHAMap := make(map[string]map[string][]byte)
    84  	metadataSHAMap[sha] = metadataByteMap
    85  
    86  	return cache.Put(metadataCacheKey, metadataSHAMap)
    87  }