Hi,
I have made changes according to the comments and also simply the main
function but am not sure if the worker go routine works.
This what i did:
type Route struct {
Name string
Method string
Pattern string
HandlerFunc http.HandlerFunc
}
var idtime = make(map[string]int64)
func UpdateData(response http.ResponseWriter, request *http.Request) {
var (
localVarHTTPMethod = http.MethodPatch
patchItems model.PatchItem
)
id := config.GetIdFromRequest(request)
if request.Method == localVarHTTPMethod {
err := json.NewDecoder(request.Body).Decode(&patchItems)
if err != nil {
common.WriteError(response, common.ErrBadRequest)
return
}
defer request.Body.Close()
idtime[id] = time.Now().Unix()
common.RespondWith3gppJsonPatchJson(response, http.StatusNoContent,
nil)
} else {
common.WriteError(response, common.ErrMethodNotAllowed)
return
}
}
var (
mu sync.Mutex
ctx = context.Background()
)
func worker() {
mu.Lock()
for keyid := range idtime {
d := time.Now().Unix() - idtime[keyid]
if d >= 60 {
// delete resouce in database after 60 seconds
_ = DeleteNFInstance(ctx, keyid)
}
}
mu.Unlock()
}
// Delete info
func DeleteNFInstance(ctx context.Context, nfinstanceId string) bool {
filter := bson.M{"_id": nfinstanceId}
_, err := db.Collection(COLLECTION).DeleteOne(ctx, filter)
if err != nil {
return false
}
return true
}
type Routes []Route
func NewRouter() *mux.Router {
router := mux.NewRouter().StrictSlash(true)
for _, route := range routes {
var handler http.Handler
handler = route.HandlerFunc
router.
Methods(route.Method).
Path(route.Pattern).
Name(route.Name).
Handler(handler)
}
return router
}
var routes = Routes{
Route{
"UpdateData",
strings.ToUpper("Patch"),
"/users/{id}",
UpdateData,
},
}
// main function
func main() {
r := NewRouter()
go worker()
fmt.Println("Start listening")
fmt.Println(http.ListenAndServe(":8080", r))
}
I appreciate your help but am still not able to it work.
On Tuesday, November 17, 2020 at 3:48:44 PM UTC+2 Shulhan wrote:
> Hi Afriyie,
>
> Looks like you almost there ;)
>
> > On 17 Nov 2020, at 20.11, Afriyie Abraham Kwabena <[email protected]>
> wrote:
> >
> > HI,
> >
> > This is what I have tried so far but am not able to get the time
> difference in seconds. I mean the time differences between the time stored
> in the map[string]time.Time and
> > the current time in seconds.
> >
> > code:
> >
> > type Server struct {
> > idtime map[string]time.Time
> > }
> >
> > var my = Server{}
> >
> > func main() {
> > r := mux.NewRouter()
> > usersData := r.PathPrefix("/users").Subrouter()
> > usersData.Path("/{id}").Methods(http.MethodPatch).HandlerFunc(UpdateData)
> >
>
> Based on my understanding (I have never use mux before), the UpdateDate
> function will be running concurrently as goroutine. Lets say that we have
> three PATCH requests at the same time, there will be three UpdateData
> running concurrently or in parallel.
>
> > fmt.Println("Start listening")
> > fmt.Println(http.ListenAndServe(":8080", r))
> > }
> >
> > func UpdateData(response http.ResponseWriter, request *http.Request) {
> >
> > var (
> > localVarHTTPMethod = http.MethodPatch
> > patchItems model.PatchItem
> > )
> >
> > id := config.GetIdFromRequest(request)
> >
> > if request.Method == localVarHTTPMethod {
> >
> > err := json.NewDecoder(request.Body).Decode(&patchItems)
> > if err != nil {
> > common.WriteError(response, common.ErrBadRequest)
> > return
> > }
> >
> > defer request.Body.Close()
> >
> > my.idtime = make(map[string]time.Time)
>
> Since the UpdateData is running independently for each request, you should
> initialize this once, in the main, otherwise each UpdateData routine will
> reset the idtime variable.
>
> > my.idtime[id] = time.Now()
> >
> > go func() {
> > for keyid, t := range my.idtime {
> >
> > ts := t.Format(time.RFC3339)
> >
> > v, err := time.Parse(time.RFC3339, ts)
> > if err != nil {
> > fmt.Println(err)
> > os.Exit(1)
> > }
> >
> > timeRemaining := getTimeRemaining(v)
> >
> > if timeRemaining.S >= 60 {
> > // delete resouce in database after 60 seconds
> > deleteResourceUsingIdkey(keyid)
> > }
> > }
> > }()
>
> Also, you should move the above goroutine to main, otherwise each call to
> UpdateData will spawn a new goroutine.
>
> If I were you I will use the Unix time [1] instead of Time object, its
> much simpler `time.Now().Unix() - my.idtime[keyid] >= 60`.
>
> BTW, beware of race condition. Test or build your program with "-race"
> option to see it by yourself. Use sync.Mutex [2] to prevent the write
> (updating the map) overlap with read (checking the elapsed seconds).
>
> [1] https://pkg.go.dev/time#Time.Unix
> [2] https://pkg.go.dev/sync#Mutex
>
> >
> > common.RespondWith3gppJsonPatchJson(response, http.StatusNoContent, nil)
> > } else {
> >
> > common.WriteError(response, common.ErrMethodNotAllowed)
> > return
> > }
>
> Another things that I can't not comment, you can simplify the code by
> returning-first, which minimize code identation.
>
> > }
> >
> > type count struct {
> > S int
> > }
> >
> > func getTimeRemaining(t time.Time) count {
> > currentTime := time.Now()
> > difference := t.Sub(currentTime)
> >
> > seconds := int(difference.Seconds())
> >
> > return count{
> > S: seconds,
> > }
> > }
> >
> > func deleteResourceUsingIdkey(idkey string) {
> > // do delete here
> > }
> >
> > Any help.
> >
>
--
You received this message because you are subscribed to the Google Groups
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/golang-nuts/eff359bb-72e2-4f8b-a265-68f395553021n%40googlegroups.com.