<commit_before>package main

import (
	"io"
	"net/http"
	"net/http/httputil"
	"path"
	"stathat.com/c/consistent"
	"strings"
)

// Builds the X-Backends header with a chain of nearest 3 backends on the
// consistent hash ring.
func BackendHeader(c *consistent.Consistent, name string) string {
	backends, _ := c.GetN(name, 3)
	// Need to shuffle these for reliable distribution of cache objects
	return strings.Join(backends, ",")
}

// Reverse proxy that selects the backend by nearest match to the request URL
// on the consistent hash ring.
func CacheProxy(c *consistent.Consistent) *httputil.ReverseProxy {
	return &httputil.ReverseProxy{
		Director: func(req *http.Request) {
			req.URL.Scheme = "http"
			backends, _ := c.GetN(req.URL.Path, 3)
			req.URL.Host = backends[0]
			req.Header.Set("X-Backends", strings.Join(backends, ","))
		},
		Transport: &http.Transport{},
	}
}

func CacheProxyManager(c *consistent.Consistent) *http.ServeMux {
	manager := http.NewServeMux()

	// RESTful interface for cache members
	// GET /members/
	// 	  Returns a list of current cache members
<commit_msg>Shuffling backends to introduce variation in chained cache lookup<commit_after>package main

import (
	"io"
	"math/rand"
	"net/http"
	"net/http/httputil"
	"path"
	"stathat.com/c/consistent"
	"strings"
)

// Sattolo shuffle
// https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle#Sattolo.27s_algorithm
func shuffle(list []string) {
	for i := range list {
		j := rand.Intn(i + 1)
		list[i], list[j] = list[j], list[i]
	}
}

// Reverse proxy that selects the backend by nearest match to the request URL
// on the consistent hash ring.
func CacheProxy(c *consistent.Consistent) *httputil.ReverseProxy {
	return &httputil.ReverseProxy{
		Director: func(req *http.Request) {
			req.URL.Scheme = "http"
			backends, _ := c.GetN(req.URL.Path, 3)
			shuffle(backends)
			req.URL.Host = backends[0]
			req.Header.Set("X-Backends", strings.Join(backends, ","))
		},
		Transport: &http.Transport{},
	}
}

func CacheProxyManager(c *consistent.Consistent) *http.ServeMux {
	manager := http.NewServeMux()

	// RESTful interface for cache members
	// GET /members/
	// 	  Returns a list of current cache members

{'fraction_non_alphanumeric': 0.13318181818181818, 'fraction_numerical': 0.006363636363636364, 'mean_word_length': 3.9572072072072073, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1099345', 'n_tokens_mistral': 828, 'n_tokens_neox': 765, 'n_words': 198}