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 <afriyie...@gmail.com> 
> 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 golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/eff359bb-72e2-4f8b-a265-68f395553021n%40googlegroups.com.

Reply via email to