设置一个 golang API,每小时查询数据库以刷新数据。

huangapple go评论79阅读模式
英文:

Setting up a golang API that queries a database every hour to refresh its data

问题

我对golang相对较新,希望能得到一些关于如何构建这个项目的高级提示。我正在尝试构建一个REST API:

  • 用户通过POST方法提供一个小的JSON数据
  • API将用户的输入数据与作为结构体切片存储的参考数据集进行比较,并计算一个值
  • 将该值返回给用户
  • 每小时从数据库查询数据,并用另一个结构体切片数据集替换原有的参考数据集。基本上,这会刷新参考数据
  • 我希望这个刷新任务是异步的,这样就不会影响用户体验

我正在使用golang的Echo框架(https://echo.labstack.com/)。以下是我在类似golang伪代码中的尝试。你会如何设计这个API以实现每小时异步刷新数据?

为了澄清,我卡在“每小时异步后台查询数据库”的部分。我不确定如何在这种情况下实现。

func main() {

	e := echo.New()
	e.POST("/", func(something) {
		
		// 这个函数查询数据库并将结果保存为结构体切片的参考数据集
		dataset := refreshDB() 

		// 对输入的JSON数据和参考数据集进行一些计算
		result := doCalcs(inputJSON, dataset)

		// 准备好返回给用户的响应JSON
		responseForUser := prepOutput(result)

		return responseForUser
	
	})
	
}
英文:

I'm relatively new to golang and could use some high-level tips on how to structure this. I'm trying to a build a REST API:

  • The user would provide a small JSON payload via POST method
  • The API compares the user’s input data against a reference dataset stored as a slice of structs and calculates a value
  • This value is returned to the user
  • Every hour a database is queried to and replaces the slice of structs dataset with another slice of structs dataset. Basically this refreshes the reference data
  • I'd like this refreshing job to be async so it doesn't slow down the user experience

I'm using the golang's Echo framework (https://echo.labstack.com/). Here is my attempt in golang-like pseudocode.
How would you structure this API to refresh the data hourly async?

To clarify, the part Im stuck on is the “query the DB every hour async in the background” bit. Im unsure how to do that in thos scenario.

func main() {

	e := echo.New()
	e.POST("/", func(something) {
		
		// This func queries the DB and saves reference dataset result as a slice of structs
		dataset := refreshDB() 

		// Does some calculations on input JSON data and reference dataset
		result := doCalcs(inputJSON, dataset)

		// Prep response in neat JSON
		responseForUser := prepOutput(result)

		return responseForUser
	
	})
	
}

答案1

得分: 2

在Go语言中,你可以使用goroutine来处理异步代码,使用ticker来定期执行代码。

package main

import (
	"fmt"
	"time"
	"sync"
)

var rwm sync.RWMutex
var sliceOfStructs []struct{/* ... */}

func main() {
	go func() {
		tick := time.NewTicker(time.Hour)
		for range tick.C {
			rwm.Lock()
			sliceOfStructs = []struct{}{ /* 使用新数据刷新 */ }
			rwm.Unlock()
		}
	}()
	
	// 启动服务器
}
  • 如果sliceOfStructs需要在多个包中访问,则需要将其导出并移动到一个非main包中,即可以被导入的包。对于rwm也是一样。
  • 确保任何读取sliceOfStructs的代码在读取之前调用rwm.RLock,在完成后调用rwm.RUnlock
  • 如果有多个goroutine需要写入sliceOfStructs,则应将rwmsync.RWMutex更改为sync.Mutex
英文:

For async code in Go you can use a goroutine, to execute the code periodically you can use a ticker.

package main

import (
	"fmt"
	"time"
	"sync"
)

var rwm sync.RWMutex
var sliceOfStructs []struct{/* ... */}

func main() {
	go func() {
		tick := time.NewTicker(time.Hour)
		for range tick.C {
			rwm.Lock()
			sliceOfStructs = []struct{}{ /* refresh with new data */ }
			rwm.Unlock()
		}
	}()
	
	// start server
}
  • If sliceOfStructs needs to be accessible across multiple packages then you'll need to export it and move it to a non-main package, i.e. one that can be imported. And do the same for rwm.
  • Make sure that any code that reads sliceOfStructs invokes rwm.RLock before reading and rwm.RUnlock when done.
  • If you have more than one goroutine that needs to write sliceOfStructs then you should change rwm from sync.RWMutex to sync.Mutex.

huangapple
  • 本文由 发表于 2021年7月16日 09:11:59
  • 转载请务必保留本文链接:https://go.coder-hub.com/68402369.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定