115 lines
2.9 KiB
Go
115 lines
2.9 KiB
Go
package chainquery
|
|
|
|
import (
|
|
"database/sql"
|
|
"fmt"
|
|
"sync"
|
|
"time"
|
|
|
|
"voidwalker/configs"
|
|
|
|
"github.com/lbryio/lbry.go/v2/extras/errors"
|
|
"github.com/sirupsen/logrus"
|
|
|
|
_ "github.com/go-sql-driver/mysql"
|
|
)
|
|
|
|
type CQApi struct {
|
|
dbConn *sql.DB
|
|
cache *sync.Map
|
|
}
|
|
|
|
var instance *CQApi
|
|
var ClaimNotFoundErr = errors.Base("claim not found")
|
|
|
|
func Init() (*CQApi, error) {
|
|
if instance != nil {
|
|
return instance, nil
|
|
}
|
|
db, err := connect()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
instance = &CQApi{
|
|
cache: &sync.Map{},
|
|
dbConn: db,
|
|
}
|
|
return instance, nil
|
|
}
|
|
|
|
func connect() (*sql.DB, error) {
|
|
db, err := sql.Open("mysql", fmt.Sprintf("%s:%s@tcp(%s)/%s?parseTime=true", configs.Configuration.Chainquery.User, configs.Configuration.Chainquery.Password, configs.Configuration.Chainquery.Host, configs.Configuration.Chainquery.Database))
|
|
return db, errors.Err(err)
|
|
}
|
|
|
|
type Claim struct {
|
|
ClaimID string `json:"claim_id"`
|
|
SdHash string `json:"sd_hash"`
|
|
ContentType string `json:"content_type"`
|
|
}
|
|
type ChainqueryCache struct {
|
|
lastFetched time.Time
|
|
claim *Claim
|
|
}
|
|
|
|
func (c *CQApi) ResolveClaim(claimName, shortID string) (*Claim, error) {
|
|
cached, ok := c.cache.Load(claimName + shortID)
|
|
if ok {
|
|
cachedCasted, _ := cached.(ChainqueryCache)
|
|
if cachedCasted.lastFetched.After(time.Now().Add(-5 * time.Minute)) {
|
|
logrus.Infoln("loaded from cache")
|
|
return cachedCasted.claim, nil
|
|
}
|
|
}
|
|
query := "SELECT claim_id, sd_hash, content_type FROM claim where name = ? AND claim_id LIKE ?"
|
|
rows, err := c.dbConn.Query(query, claimName, fmt.Sprintf("%s%%", shortID))
|
|
if err != nil {
|
|
return nil, errors.Err(err)
|
|
}
|
|
defer rows.Close()
|
|
|
|
for rows.Next() {
|
|
var claim Claim
|
|
err = rows.Scan(&claim.ClaimID, &claim.SdHash, &claim.ContentType)
|
|
if err != nil {
|
|
return nil, errors.Err(err)
|
|
}
|
|
c.cache.Store(claimName+shortID, ChainqueryCache{
|
|
lastFetched: time.Now(),
|
|
claim: &claim,
|
|
})
|
|
return &claim, nil
|
|
}
|
|
return nil, ClaimNotFoundErr
|
|
}
|
|
|
|
func (c *CQApi) ResolveClaimByChannel(claimName, channelID, channelName string) (*Claim, error) {
|
|
cached, ok := c.cache.Load(claimName + channelID)
|
|
if ok {
|
|
cachedCasted, _ := cached.(ChainqueryCache)
|
|
if cachedCasted.lastFetched.After(time.Now().Add(-5 * time.Minute)) {
|
|
logrus.Infoln("loaded from cache")
|
|
return cachedCasted.claim, nil
|
|
}
|
|
}
|
|
query := "SELECT claim_id, sd_hash, content_type FROM claim where name = ? AND publisher_id = (select claim_id from claim where claim_id like ? and name = ? order by id desc limit 1)"
|
|
rows, err := c.dbConn.Query(query, claimName, fmt.Sprintf("%s%%", channelID), channelName)
|
|
if err != nil {
|
|
return nil, errors.Err(err)
|
|
}
|
|
defer rows.Close()
|
|
|
|
for rows.Next() {
|
|
var claim Claim
|
|
err = rows.Scan(&claim.ClaimID, &claim.SdHash, &claim.ContentType)
|
|
if err != nil {
|
|
return nil, errors.Err(err)
|
|
}
|
|
c.cache.Store(claimName+channelID, ChainqueryCache{
|
|
lastFetched: time.Now(),
|
|
claim: &claim,
|
|
})
|
|
return &claim, nil
|
|
}
|
|
return nil, ClaimNotFoundErr
|
|
}
|