Merge pull request #1 from doubtingben/cache2go

Cache2go
This commit is contained in:
Ben Wilson 2020-07-22 09:40:18 -04:00 committed by GitHub
commit 70e63e3336
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 56 additions and 31 deletions

1
go.mod
View File

@ -8,6 +8,7 @@ require (
github.com/gobuffalo/packr v1.30.1
github.com/kelseyhightower/envconfig v1.4.0
github.com/lib/pq v1.7.0
github.com/muesli/cache2go v0.0.0-20200423001931-a100c5aac93f
github.com/onsi/gomega v1.10.1 // indirect
github.com/rogpeppe/go-internal v1.6.0 // indirect
github.com/ybbus/jsonrpc v2.1.2+incompatible

2
go.sum
View File

@ -48,6 +48,8 @@ github.com/lib/pq v1.7.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/muesli/cache2go v0.0.0-20200423001931-a100c5aac93f h1:dBzTzAKOh89fTvdQ3XlXupMExvLty90V1rrpChTAQAY=
github.com/muesli/cache2go v0.0.0-20200423001931-a100c5aac93f/go.mod h1:414R+qZrt4f9S2TO/s6YVQMNAXR2KdwqQ7pW+O4oYzU=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=

84
main.go
View File

@ -18,11 +18,13 @@ import (
"github.com/gobuffalo/packr"
"github.com/kelseyhightower/envconfig"
_ "github.com/lib/pq"
"github.com/muesli/cache2go"
"github.com/ybbus/jsonrpc"
)
const tapAmount = 1.0
const tapWaitMinutes = 2
const opStatusWaitSeconds = 120
type TapRequest struct {
NetworkAddress string
@ -69,6 +71,7 @@ type Zfaucet struct {
ZcashNetwork string
FundingAddress string
TapRequests []*TapRequest
TapCache *cache2go.CacheTable
ZfaucetHTML string
}
@ -98,6 +101,27 @@ func (z *Zfaucet) ClearCache() {
}
}
func (z *Zfaucet) UpdateZcashInfo() {
for {
z.UpdatedChainInfo = time.Now()
zChainInfo, err := getBlockchainInfo(z.RPCConnetion)
if err != nil {
fmt.Printf("Failed to get blockchaininfo: %s\n", err)
} else {
z.CurrentHeight = zChainInfo.Blocks
z.ZcashNetwork = zChainInfo.Chain
}
zVersion, err := getInfo(z.RPCConnetion)
if err != nil {
fmt.Printf("Failed to getinfo: %s\n", err)
} else {
z.ZcashdVersion = strconv.Itoa(zVersion.Version)
}
fmt.Println("Updated Zcashd Info")
time.Sleep(time.Second * 30)
}
}
func (z *Zfaucet) WaitForOperation(opid string) (os OperationStatus, err error) {
var opStatus []struct {
CreationTime int `json:"creation_time"`
@ -115,7 +139,7 @@ func (z *Zfaucet) WaitForOperation(opid string) (os OperationStatus, err error)
fmt.Printf("opList: %s\n", opList)
fmt.Printf("parentList: %s\n", parentList)
// Wait for a few seconds for the operational status to become available
for i := 0; i < 10; i++ {
for i := 0; i < opStatusWaitSeconds; i++ {
if err := z.RPCConnetion.CallFor(
&opStatus,
"z_getoperationresult",
@ -176,11 +200,13 @@ func (z *Zfaucet) ZSendManyFaucet(remoteAddr string, remoteWallet string) (opSta
if opStatus.Status != "success" {
return opStatus, fmt.Errorf("Failed to send funds: %s", err)
}
z.TapRequests = append(z.TapRequests, &TapRequest{
tapRequest := &TapRequest{
NetworkAddress: remoteAddr,
WalletAddress: remoteWallet,
RequestedAt: time.Now(),
})
}
z.TapCache.Add(remoteAddr, tapWaitMinutes*60*time.Second, tapRequest)
z.TapRequests = append(z.TapRequests, tapRequest)
return opStatus, err
}
@ -224,6 +250,7 @@ func main() {
basicAuth := base64.StdEncoding.EncodeToString([]byte(zConfig.RPCUser + ":" + zConfig.RPCPassword))
var z Zfaucet
z.TapCache = cache2go.Cache("tapRequests")
z.FundingAddress = zConfig.FundingAddress
z.Operations = make(map[string]OperationStatus)
z.RPCConnetion = jsonrpc.NewClientWithOpts("http://"+zConfig.RPCHost+":"+zConfig.RPCPort,
@ -232,19 +259,8 @@ func main() {
"Authorization": "Basic " + basicAuth,
}})
zChainInfo, err := getBlockchainInfo(z.RPCConnetion)
if err != nil {
log.Fatalf("Failed to get blockchaininfo: %s", err)
}
z.CurrentHeight = zChainInfo.Blocks
z.ZcashNetwork = zChainInfo.Chain
zVersion, err := getInfo(z.RPCConnetion)
if err != nil {
log.Fatalf("Failed to getinfo: %s", err)
}
z.ZcashdVersion = strconv.Itoa(zVersion.Version)
go z.ClearCache()
go z.UpdateZcashInfo()
box := packr.NewBox("./templates")
z.ZfaucetHTML, err = box.FindString("zfaucet.html")
@ -285,15 +301,13 @@ func (z *Zfaucet) home(w http.ResponseWriter, r *http.Request) {
}
switch r.Method {
case http.MethodPost:
for _, n := range z.TapRequests {
fmt.Printf("Checking RemoteAddress: '%#v' - '%#v'\n", r.RemoteAddr, n.NetworkAddress)
if n.NetworkAddress == r.RemoteAddr {
tData.Msg = fmt.Sprintf("You may only tap the faucet every %d minutes\nPlease try again later\n", tapWaitMinutes)
break
} else {
fmt.Printf("It doesn't match... \n")
}
res, err := z.TapCache.Value(r.RemoteAddr)
if err == nil {
fmt.Println("Found value in cache:", res.Data().(*TapRequest).NetworkAddress)
tData.Msg = fmt.Sprintf("You may only tap the faucet every %d minutes\nPlease try again later\n", tapWaitMinutes)
break
} else {
fmt.Println("Error retrieving value from cache:", err)
}
if err := checkFaucetAddress(r.FormValue("address")); err != nil {
tData.Msg = fmt.Sprintf("Invalid address: %s", err)
@ -304,7 +318,7 @@ func (z *Zfaucet) home(w http.ResponseWriter, r *http.Request) {
tData.Msg = fmt.Sprintf("Failed to send funds: %s", err)
break
}
tData.Msg = fmt.Sprintf("Successfully submitted operation: %s", opStatus)
tData.Msg = fmt.Sprintf("Successfully submitted operation, transaction: %s", opStatus.TxID)
}
w.Header().Set("Content-Type", "text/html")
tmpl, err := template.New("name").Parse(z.ZfaucetHTML)
@ -340,18 +354,26 @@ func (z *Zfaucet) balance(w http.ResponseWriter, r *http.Request) {
// opsStatus
func (z *Zfaucet) opsStatus(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
var ops *[]string
if err := z.RPCConnetion.CallFor(&ops, "z_listoperationids"); err != nil {
// tData is the html template data
tData := struct {
Z *Zfaucet
Ops *[]string
Type string
}{
z,
nil,
"opsStatus",
}
if err := z.RPCConnetion.CallFor(&tData.Ops, "z_listoperationids"); err != nil {
http.Error(w, err.Error(), 500)
return
}
out, err := json.Marshal(ops)
w.Header().Set("Content-Type", "text/html")
tmpl, err := template.New("name").Parse(z.ZfaucetHTML)
if err != nil {
http.Error(w, err.Error(), 500)
return
}
fmt.Fprintf(w, string(out))
tmpl.Execute(w, tData)
}
// addresses