[go-nuts] Multipar/related Request in golang
Hi, AM trying to prepare a multipart/related message which involve JSON data n1n2Request.JsonData and a binary data binaryData to be sent in HTTP request, however, am having issue abou how to set the boundries in the function below. The server is logging "Failed to parse boundary. missing/invalide boundary". I need help to set the boundaries correctly in the function below. Thanks in advance. func CreateMultipartRelatedN1N2MessageTransferRequest(inputData models.InputData) (*models.N1N2MessageTransferRequest, string, error) { // Create a buffer to hold the multipart data var buf bytes.Buffer // Create a multipart writer with "multipart/related" type writer := multipart.NewWriter(&buf) // Define the boundary for the multipart/related content boundary := writer.Boundary() // Create the N1N2MessageTransferRequest object n1n2Request := models.N1N2MessageTransferRequest{} // Get LMF instanceID (example placeholder, replace with actual logic) _, _, nfId, _, _ := config.Cfg.GetServerInfo() // Populate the N1N2MessageTransferReqData n1n2Request.JsonData = &models.N1N2MessageTransferReqData{ N1MessageContainer: &models.N1MessageContainer{ N1MessageClass: models.N1MessageClass_LPP, N1MessageContent: &models.RefToBinaryData{ ContentId: "N1LoInformation", }, NfId: nfId, }, LcsCorrelationId: inputData.CorrelationID, N1n2FailureTxfNotifURI: "", } // Add the JSON part as the root body part jsonPartHeader := textproto.MIMEHeader{} jsonPartHeader.Set("Content-Type", "application/json; charset=UTF-8") jsonPartHeader.Set("Content-ID", "jsondata") jsonPart, err := writer.CreatePart(jsonPartHeader) if err != nil { return nil, "", fmt.Errorf("error creating JSON part: %v", err) } jsonBytes, err := json.Marshal(n1n2Request.JsonData) if err != nil { return nil, "", fmt.Errorf("error marshaling JSON data: %v", err) } _, err = jsonPart.Write(jsonBytes) if err != nil { return nil, "", fmt.Errorf("error writing JSON data: %v", err) } // Create the LPP message lppMessage := models.LPPMessage{ TransactionID: &models.LPPTransactionID{ TransactionNumber: common.GenerateNumber(), Initiator: int(models.LocationServer), }, SequenceNumber: common.GenerateNumber(), LPPMessageBody: &models.LPPMessageBody{ C1: &models.C1{ RequestLocationInformation: &models.RequestLocationInformation{ CriticalExtensions: &models.CriticalExtensions{ C1: &models.CriticalExtensionsC1{ RequestLocationInformationR9: &models.RequestLocationInformationR9IEs{ CommonIEsRequestLocationInformation: &models.CommonIEsRequestLocationInformation{ LocationInformationType: int(models.LocationEstimateRequired), PeriodicalReporting: &models.PeriodicalReportingCriteria{ ReportingAmount: int(models.RA1), ReportingInterval: int(models.RI32), }, LocationCoordinateTypes: &models.LocationCoordinateTypes{ EllipsoidPoint: true, }, VelocityTypes: &models.VelocityTypes{ HorizontalVelocity: true, }, }, }, }, }, }, }, }, EndTransaction: true, } // Encode the LPP message using ASN.1 PER encoding binaryData, err := aper.Marshal(lppMessage) if err != nil { logger.Log.Error().Msgf("Error encoding, aper.Marshal error: %v", err) return nil, "", err } // Add the binary part with a Content-ID header binaryPartHeader := textproto.MIMEHeader{} binaryPartHeader.Set("Content-ID", "n1message") binaryPartHeader.Set("Content-Type", "application/vnd.3gpp.5gnas") binaryPart, err := writer.CreatePart(binaryPartHeader) if err != nil { return nil, "", fmt.Errorf("error creating binary part: %v", err) } // Write the encoded binary data to the binary part _, err = binaryPart.Write(binaryData) if err != nil { return nil, "", fmt.Errorf("error writing binary data: %v", err) } // Close the multipart writer to finalize the form data err = writer.Close() if err != nil { return nil, "", fmt.Errorf("error closing multipart writer: %v", err) } // Attach the buffer's content as the binary data
[go-nuts] How to detect HTTP client stop polling at the server side
Hi, My question is about multiple HTTP client polling an HTTP server randomly with a PATCH request to update a resource at the server running in front of MongoDB. The clients poll with their different ids and a valid time in their request. At the server, I can keep their ids and their different times. How can detect at the server if a specific client stop polling. I would like to write a function that detect at the HTTP server if a specific client stop polling and then remove its resources after some time from a database. Am using gorilla/mux package for the server. Any help, am new to Golang programming. Thanks in advance -- 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/8658410c-5cac-4dff-80e3-ebb1b8bbb5een%40googlegroups.com.
Re: [go-nuts] How to detect HTTP client stop polling at the server side
Hi , You are right but am new to programming and currently this what i have done. I have an http server handler that receives the PATCH request and stores the id and the current time stamp of the request. But my problem is how to write the worker function to do the clean up every X seconds. Code: 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() var idtime = make(map[string]string) delete(idtime, id) // delete if already exist idtime[id] = time.Now() // store id and time stamp in map // how do i write a worker to the clean up after every X seconds? } else { common.WriteError(response, common.ErrMethodNotAllowed) return } } BR Abraham On Sunday, November 15, 2020 at 9:01:27 AM UTC+2 Shulhan wrote: > > > On 14 Nov 2020, at 20.06, Afriyie Abraham Kwabena > wrote: > > > > Hi, > > > > My question is about multiple HTTP client polling an HTTP server > randomly with a PATCH request to update a resource at the server running in > front of MongoDB. The clients poll with their different ids and a valid > time in their request. At the server, I can keep their ids and their > different times. > > How can detect at the server if a specific client stop polling. I would > like to write a function that detect at the HTTP server if a specific > client stop polling and then remove its resources after some time from a > database. Am using gorilla/mux package for the server. Any help, am new to > Golang programming. > > > > I think this is not Go specific, but more like engineering in general. > > My suggestion is you can store the last time when user request to PATCH > endpoint in some storage or internal memory (like map[userID]timestamp) and > then have some worker that check the timestamp to clean it up every X > seconds or minutes. -- 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/7798fe2c-d176-4514-8fe0-04b6e19f4399n%40googlegroups.com.
Re: [go-nuts] How to detect HTTP client stop polling at the server side
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) 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) 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) } } }() common.RespondWith3gppJsonPatchJson(response, http.StatusNoContent, nil) } else { common.WriteError(response, common.ErrMethodNotAllowed) return } } 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. On Tuesday, November 17, 2020 at 10:34:39 AM UTC+2 Anderson Queiroz wrote: > Just one thing to keep in mind. Likely you have more than one serve > instance running to process the requests. Thus it might happen the client > will poll a different server on every request. Just imagine you have > servers A, B, C behind a load balance and the domain example.com. As the > client is pooling example.com, the first request might reach A, the > second B and the third C. Now you have the 3 servers tracking the same > client. It might happen server A doesn't receive any request from the > client for a while, but not because the client isn't pooling any more, but > because all requests are being directed to either B or C. > > On Tuesday, 17 November 2020 at 07:12:18 UTC+1 Shulhan wrote: > >> >> >> > On 16 Nov 2020, at 16.24, Afriyie Abraham Kwabena >> wrote: >> > >> > Hi , >> > >> > You are right but am new to programming and currently this what i have >> done. >> > I have an http server handler that receives the PATCH request and >> stores the id and the current time stamp of the request. >> > But my problem is how to write the worker function to do the clean up >> every X seconds. >> > >> > Code: >> > 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() >> > >> > var idtime = make(map[string]string) >> > >> > delete(idtime, id) // delete if already exist >> > idtime[id] = time.Now() // store id and time stamp in map >> >> You should store idtime inside the server/service type (the one that have >> HTTP handlers). For example, >> >> >> type Server struct { >> idtime map[string]string >> } >> >> func (my *Server) UpdateData(...) { >> ... >> my.idtime[id] = time.Now() >> ... >> } >> >> >> > >> > // how do i write a worker to the clean up after every X seconds? >> > >> >
Re: [go-nuts] How to detect HTTP client stop polling at the server side
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 { Namestring 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 > 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 databa
Re: [go-nuts] How to detect HTTP client stop polling at the server side
Hi, The UpdateData function is the HTTP handler for the route which matches the URL and is called after the mux.Router after receiving an incoming request matches the incoming request against the registered route. BR Afriyie On Tuesday, November 17, 2020 at 7:33:50 PM UTC+2 Afriyie Abraham Kwabena wrote: > 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 { > Namestring > 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 >> 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 >
Re: [go-nuts] How to detect HTTP client stop polling at the server side
Hi Sulhan, Anderson, Thanks for your guidance. It works now using time.Ticker func worker() { tiker := time.NewTicker(30 * time.Second) for _ = range tiker.C { 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() } } BR Abraham On Tuesday, November 17, 2020 at 9:41:01 PM UTC+2 Shulhan wrote: > > > > On 18 Nov 2020, at 01.06, Afriyie Abraham Kwabena > wrote: > > > > Hi, > > > > The UpdateData function is the HTTP handler for the route which matches > the URL and is called after the mux.Router after receiving an incoming > request matches the incoming request > > against the registered route. > > ... > > > 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() > > > > We still may have data race here. > > > > > 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() > > } > > > > ... > > > // 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. > > > > Looks like your worker only loop once and then it finished. Either you use > time.Sleep() to repeat the loop inside loop or use time.Ticker [1]. > > [1] https://pkg.go.dev/time#Ticker > > -- 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/cc7b885f-074a-4b23-9f4c-08d4a3a7ac62n%40googlegroups.com.
[go-nuts] How to detect if transport connection break
Hi, My basic understanding of HTTP protocol is that an HTTP client sent request, get response from the HTTP server and then the connection is closed. My question is how can an HTTP client detect if the underling transport connection break. For example if the HTTP server shutdown, is there a way to detect that at the client so that the client can start a persistent request. If possible, how can I do that in golang HTTP client? BR Abraham -- 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/4937b529-c1aa-4425-8b81-01214c1fc1f7n%40googlegroups.com.
Re: [go-nuts] How to detect if transport connection break
Hi, Am new to programming and if you could explain further what you mean by long lived process. On Friday, November 20, 2020 at 11:41:42 AM UTC+2 amits...@gmail.com wrote: > > > On Fri, 20 Nov 2020, 7:51 pm Afriyie Abraham Kwabena, < > afriyie...@gmail.com> wrote: > >> >> Hi, >> >> My basic understanding of HTTP protocol is that an HTTP client sent >> request, get response from the HTTP server and then the connection is >> closed. >> >> My question is how can an HTTP client detect if the underling transport >> connection break. For example if the HTTP server shutdown, is there a way >> to detect that at the client so that the client can start a persistent >> request. >> >> If possible, how can I do that in golang HTTP client? >> > > Are you thinking about implementing a connection pool for your long lived > process? > > > >> BR >> Abraham >> >> >> -- >> 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...@googlegroups.com. >> To view this discussion on the web visit >> https://groups.google.com/d/msgid/golang-nuts/4937b529-c1aa-4425-8b81-01214c1fc1f7n%40googlegroups.com >> >> <https://groups.google.com/d/msgid/golang-nuts/4937b529-c1aa-4425-8b81-01214c1fc1f7n%40googlegroups.com?utm_medium=email&utm_source=footer> >> . >> > -- 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/ce2735a8-68e7-47e1-9eb4-59a825b1eb94n%40googlegroups.com.
Re: [go-nuts] How to detect if transport connection break
Hi, Yes, that is what intend to implement. Can you help with some information about how I could implement it. If possible some libraries or example code. Abraham On Friday, November 20, 2020 at 1:07:12 PM UTC+2 Afriyie Abraham Kwabena wrote: > Hi, > > Am new to programming and if you could explain further what you mean by > long lived process. > > > On Friday, November 20, 2020 at 11:41:42 AM UTC+2 amits...@gmail.com > wrote: > >> >> >> On Fri, 20 Nov 2020, 7:51 pm Afriyie Abraham Kwabena, < >> afriyie...@gmail.com> wrote: >> >>> >>> Hi, >>> >>> My basic understanding of HTTP protocol is that an HTTP client sent >>> request, get response from the HTTP server and then the connection is >>> closed. >>> >>> My question is how can an HTTP client detect if the underling transport >>> connection break. For example if the HTTP server shutdown, is there a way >>> to detect that at the client so that the client can start a persistent >>> request. >>> >>> If possible, how can I do that in golang HTTP client? >>> >> >> Are you thinking about implementing a connection pool for your long lived >> process? >> >> >> >>> BR >>> Abraham >>> >>> >>> -- >>> 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...@googlegroups.com. >>> To view this discussion on the web visit >>> https://groups.google.com/d/msgid/golang-nuts/4937b529-c1aa-4425-8b81-01214c1fc1f7n%40googlegroups.com >>> >>> <https://groups.google.com/d/msgid/golang-nuts/4937b529-c1aa-4425-8b81-01214c1fc1f7n%40googlegroups.com?utm_medium=email&utm_source=footer> >>> . >>> >> -- 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/d2125284-5529-4c95-82c7-3a8dac7fde78n%40googlegroups.com.
Re: [go-nuts] How to detect HTTP client stop polling at the server side
Hi, Am experiancing data race warning with my pollingworker function below even though when i build with the -race flag i do not get any error. Any help? func PollingWorker() { tiker := time.NewTicker(60 * time.Second) for _ = range tiker.C { mu.Lock() for keyid := range idtime { d := time.Now().Unix() - idtime[keyid] if d >= 60 { // Find nfinstance using keyid nfinstanceProfile, err := config.Conf.FindNFInstanceProfileById(ctx, keyid) if err != nil { config.Logrus.Error("Could not find NF Instance Profile with ID :" + keyid + " to SUSPEND Status") } // change nfStatus of nfinstance to SUSPENDED err = config.Conf.SuspendNFInstanceNfStatus(ctx, nfinstanceProfile, keyid) if err != nil { config.Logrus.Error(err) } delete(idtime, keyid) } } mu.Unlock() } } BR Abraham On Wednesday, November 18, 2020 at 10:51:49 AM UTC+2 Afriyie Abraham Kwabena wrote: > Hi Sulhan, Anderson, > > Thanks for your guidance. It works now using time.Ticker > > func worker() { > tiker := time.NewTicker(30 * time.Second) > for _ = range tiker.C { > > 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() > } > } > > BR > Abraham > > > > On Tuesday, November 17, 2020 at 9:41:01 PM UTC+2 Shulhan wrote: > >> >> >> > On 18 Nov 2020, at 01.06, Afriyie Abraham Kwabena >> wrote: >> > >> > Hi, >> > >> > The UpdateData function is the HTTP handler for the route which matches >> the URL and is called after the mux.Router after receiving an incoming >> request matches the incoming request >> > against the registered route. >> >> ... >> >> > 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() >> > >> >> We still may have data race here. >> >> > >> > 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() >> > } >> > >> >> ... >> >> > // 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. >> > >> >> Looks like your worker only loop once and then it finished. Either you >> use time.Sleep() to repeat the loop inside loop or use time.Ticker [1]. >> >> [1] https://pkg.go.dev/time#Ticker >> >> -- 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/9db5a074-0b0a-4f3a-ab20-7c5d67f458a0n%40googlegroups.com.
Re: [go-nuts] How to detect HTTP client stop polling at the server side
Hi, Yes from the warning it prints the handler function below and after google searching what i did was to mutex.Lock and Unlock the handler function and no warning again. However, my google search people mention of using channels instead of mutex. What I would like to ask is, using mutex OK and if not the best way of solving it, how can i use channels in this case. Handler function below: func UpdateNFInstance(response http.ResponseWriter, request *http.Request) { mu.Lock() defer mu.Unlock() var ( localVarHTTPMethod = http.MethodPatch ctx= context.Background() patchItems model.PatchItem ) id := config.GetIdFromRequest(request) if request.Method == localVarHTTPMethod { if request.Header.Get("Content-Type") != "application/json-patch+json" { common.WriteError(response, common.ErrStatusUnsupportedMediaTypePatch) return } err := json.NewDecoder(request.Body).Decode(&patchItems) if err != nil { common.WriteError(response, common.ErrBadRequest) return } defer request.Body.Close() delete(idtime, id) // delete value in map if exit idtime[id] = time.Now().Unix() nfProfile, err := config.Conf.FindNFInstanceProfileById(ctx, id) if err != nil { common.WriteError(response, common.ErrNotFound) return } if patchItems.Path == "/nfStatus" { nfProfile.NfStatus = patchItems.Value nfProfile.LoadTimeStamp = time.Now().String() success := config.Conf.UpdateNFInstanceHeartBeatNfStatus(ctx, nfProfile, id) if !success { common.WriteError(response, common.ErrInternalServer) return } if request.URL.Scheme != "" { scheme = request.URL.Scheme } response.Header().Set("Content-Location", scheme+"://"+request.Host+request.URL.Path) response.Header().Set("Response-Desc", "Success") common.RespondWith3gppJSONPatchJSON(response, http.StatusNoContent, nil) } else { // patchItems.Path == "/load" information v, err := strconv.Atoi(patchItems.Value) if err != nil { config.Logrus.Errorf("Failed to convert Patch Item Value string to integer: %s", err.Error()) } nfProfile.Load = int32(v) nfProfile.LoadTimeStamp = time.Now().String() success := config.Conf.UpdateNFInstanceHeartBeatLoad(ctx, nfProfile, id) if !success { common.WriteError(response, common.ErrInternalServer) return } if request.URL.Scheme != "" { scheme = request.URL.Scheme } response.Header().Set("Content-Location", scheme+"://"+request.Host+request.URL.Path) response.Header().Set("Response-Desc", "Success") common.RespondWith3gppJSONPatchJSON(response, http.StatusNoContent, nil) } } else { common.WriteError(response, common.ErrMethodNotAllowed) return } } BR Abraham On Friday, November 27, 2020 at 6:38:52 AM UTC+2 Shulhan wrote: > > > > On 27 Nov 2020, at 07.06, Afriyie Abraham Kwabena > wrote: > > > > Hi, > > > > Am experiencing data race warning with my pollingworker function below > even though when i build with the -race flag i do not get any error. Any > help? > > > > Usually when you got data race warning it will print the line that cause > read and write race condition. Pay attention to both lines and I think you > will find the cause. > > It's kind of hard to figure it out only through a single function. It > could be in config.Conf or in function that manipulate idtime outside the > pollingworker. > > -- 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/9fae8852-b60d-4c76-9939-b997db3d685cn%40googlegroups.com.
Re: [go-nuts] How to detect HTTP client stop polling at the server side
() /home/xxx/go/pkg/mod/golang.org/x/net@v0.0.0-20201031054903-ff519b6c9102/http2/server.go:2152 +0xc5 Previous read at 0x00cf7a88 by goroutine 18: nfnrfapi/services/manag.PollingWorker() /home/xxx/go/src/nfnrfapi/services/manag/api_nf_instance_id_document_Update.go:112 +0x1c4 Goroutine 48 (running) created at: golang.org/x/net/http2.(*serverConn).processHeaders() /home/xxx/go/pkg/mod/golang.org/x/net@v0.0.0-20201031054903-ff519b6c9102/http2/server.go:1882 +0x924 golang.org/x/net/http2.(*serverConn).processFrame() /home/xxx/go/pkg/mod/golang.org/x/net@v0.0.0-20201031054903-ff519b6c9102/http2/server.go:1410 +0x41e golang.org/x/net/http2.(*serverConn).processFrameFromReader() /home/xxx/go/pkg/mod/golang.org/x/net@v0.0.0-20201031054903-ff519b6c9102/http2/server.go:1368 +0x7d9 golang.org/x/net/http2.(*serverConn).serve() /home/xxx/go/pkg/mod/golang.org/x/net@v0.0.0-20201031054903-ff519b6c9102/http2/server.go:869 +0x14fc golang.org/x/net/http2.(*Server).ServeConn() /home/xxx/go/pkg/mod/golang.org/x/net@v0.0.0-20201031054903-ff519b6c9102/http2/server.go:472 +0xdc4 golang.org/x/net/http2.ConfigureServer.func1() /home/xxx/go/pkg/mod/golang.org/x/net@v0.0.0-20201031054903-ff519b6c9102/http2/server.go:298 +0x11e net/http.(*conn).serve() /usr/local/go/src/net/http/server.go:1834 +0x1d5b Goroutine 18 (running) created at: main.main() /home/xxx/go/src/nfnrfapi/main.go:41 +0x2c6 On Friday, November 27, 2020 at 8:14:48 AM UTC+2 Afriyie Abraham Kwabena wrote: > Hi, > > Yes from the warning it prints the handler function below and after google > searching what i did was to mutex.Lock and Unlock the handler function and > no warning again. > However, my google search people mention of using channels instead of > mutex. What I would like to ask is, using mutex OK and if not the best way > of solving it, how can i use > channels in this case. > > Handler function below: > > func UpdateNFInstance(response http.ResponseWriter, request *http.Request) > { > > mu.Lock() > defer mu.Unlock() > > > var ( > localVarHTTPMethod = http.MethodPatch > ctx= context.Background() > > patchItems model.PatchItem > ) > > id := config.GetIdFromRequest(request) > > if request.Method == localVarHTTPMethod { > > if request.Header.Get("Content-Type") != > "application/json-patch+json" { > common.WriteError(response, > common.ErrStatusUnsupportedMediaTypePatch) > return > > } > > err := json.NewDecoder(request.Body).Decode(&patchItems) > if err != nil { > common.WriteError(response, common.ErrBadRequest) > return > } > > defer request.Body.Close() > > delete(idtime, id) // delete value in map if exit > > idtime[id] = time.Now().Unix() > > nfProfile, err := config.Conf.FindNFInstanceProfileById(ctx, id) > if err != nil { > common.WriteError(response, common.ErrNotFound) > return > } > > if patchItems.Path == "/nfStatus" { > > nfProfile.NfStatus = patchItems.Value > nfProfile.LoadTimeStamp = time.Now().String() > > success := config.Conf.UpdateNFInstanceHeartBeatNfStatus(ctx, > nfProfile, id) > if !success { > common.WriteError(response, common.ErrInternalServer) > return > } > > if request.URL.Scheme != "" { > scheme = request.URL.Scheme > } > response.Header().Set("Content-Location", > scheme+"://"+request.Host+request.URL.Path) > response.Header().Set("Response-Desc", "Success") > common.RespondWith3gppJSONPatchJSON(response, > http.StatusNoContent, nil) > > } else { > // patchItems.Path == "/load" information > v, err := strconv.Atoi(patchItems.Value) > if err != nil { > config.Logrus.Errorf("Failed to convert Patch Item Value > string to integer: %s", err.Error()) > } > > nfProfile.Load = int32(v) > nfProfile.LoadTimeStamp = time.Now().String() > > success := config.Conf.UpdateNFInstanceHeartBeatLoad(ctx, > nfProfile, id) > if !success { > common.WriteError(response, common.ErrInternalServer) > return > } > > if request.URL.Scheme != "" { > scheme
Re: [go-nuts] How to detect HTTP client stop polling at the server side
Hi, THanks!! BR Abraham On Friday, November 27, 2020 at 11:12:53 AM UTC+2 b.ca...@pobox.com wrote: > On Friday, 27 November 2020 at 06:14:48 UTC Afriyie Abraham Kwabena wrote: > >> What I would like to ask is, using mutex OK and if not the best way of >> solving it, how can i use >> channels in this case. >> > > There's nothing wrong with mutex, but you can use channels for a more > native-Go experience. > This video is well worth watching: > https://www.youtube.com/watch?v=5zXAHh5tJqQ > > In short, you can get mutex or semaphore-like behaviour by having a > channel with fixed depth, and putting/pulling values from it. > Playground <https://play.golang.org/p/Vg-c8v7N0-6> > > mutex := make(chan struct{}, 1) > ... > > mutex <- struct{}{} > ... do stuff > <-mutex > > -- 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/e59c6a22-030c-479a-ba8a-b61948307b62n%40googlegroups.com.
[go-nuts] How to design HTTP request between HTTP servers
Hi, I have been learning Golang for some few months now but still find it difficult to design some applications. I have two HTTP servers A and B and would like to do the following 1. server A send an HTTP PUT request with JSON body to server B. 2. If server B is not available, server A retry until server B is up and respond to the request 3. In server B response body is a timer value received by server A 4. Server B uses the timer value (eg 45) to send a PATCH request using the value as interval. For example in this case, server A send the PATCH request to server B every 45 seconds. 5. Server B respond to the PATCH request with either HTTP status code 204 or status code 404. 6. If status code is 204, that is OK, server A continues to send the PATCH request using the 45 seconds interval. 7. If the response status is 404, server A have to start the process again from step 1 again to step 6 when 204 status code is received. I have tried to write some code which works but restarting from step 1 when 404 status code is received does not work. Also am not sure if my application design is good enough. Any help and comments about my application design. Below is my code var ( ContentLocation string Timer int32 mu sync.Mutex ) func SendPUTMessageToServerB() { msgbytes, err := ioutil.ReadFile("./msg.json") ... locProfilebytes, err := json.Marshal(pcfprofile) ... locVarNRFUrl := "server B url" profile, resp, err := HandlePUTMessage(locProfilebytes, locVarNRFUrl) status := resp.StatusCode if status == http.StatusOK { logrus.Println("PUT mesage Update SUCCESS") } else if status == http.StatusCreated { logrus.Println("PUT message SUCCESS") } else { logrus.Println(fmt.Errorf("Wrong status code returned by server B %d", status)) } ContentLocation = resp.Header.Get("Location") Timer = profile.TimerValue } func HandlePUTMessage(filebyte []byte, VarPath string) (Profile, *http.Response, error) { var ( // Set client and set url localVarHTTPMethod = http.MethodPut nfp Profile ) req, err := http.NewRequest(localVarHTTPMethod, VarPath, bytes.NewBuffer(filebyte)) if err != nil { logrus.Error(err) } req.Close = true req.Header.Set("Content-Type", "application/json") backoff := 1 for { res, err := Client.Do(req) if err != nil || res == nil { logrus.Println("Server A Trying to send PUT request ...") backoff *= 2 if backoff > 20 { backoff = 20 } time.Sleep(time.Duration(backoff) * time.Second) continue } defer func() { if resCloseErr := res.Body.Close(); resCloseErr != nil { logrus.Errorf("Response body cannot close: %+v", resCloseErr) } }() bodybytes, err := ioutil.ReadAll(res.Body) //localVarHTTPResponse.Body.Close() if err != nil { logrus.Error(err) return nfp, res, err } json.Unmarshal(bodybytes, &nfp) return nfp, res, nil } } // Send PATCH message to server B func PATCHMessage() (err error) { ... patchitembytes, err := json.Marshal(patchitem) ... req, err := http.NewRequest("PATCH", ContentLocation, bytes.NewBuffer(patchitembytes)) req.Header.Set("Content-Type", "application/json-patch+json") response, err := transport.Client.Do(req) // for dev defer response.Body.Close() status := response.StatusCode if status == http.StatusNoContent { logrus.Info("PATCH message SUCCESS") } else if status == http.StatusNotFound { // Here I would like to restart PUT message if status code is 404 logrus.Println("Heart-Beat Message FAILED") } return err } // Send a patch message every Timer value func SendPATCHMessageEveryTimerValue() { for { ticker := time.NewTicker(time.Duration(Timer) * time.Second) mu.Lock() for _ = range ticker.C { err := PATCHMessage() if err != nil { SendPUTMessage() } } mu.Unlock() } } func main() { SendPUTMessageToServerB() go SendPATCHMessageEveryTimerValue() } -- 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/a2481944-2a5c-467b-ba39-6e355fe219aan%40googlegroups.com.