Pattern for handling HTTP requests via channels
I am writing a web application where I have a long running goroutine.
I want to delegate all HTTP requests to this goroutine via channels.
The pattern that I have come across is:
// Internal long running goroutine
for{
select{
case e := <-event: //web request
req := e.req
// do something
....
select {
case <-ctx.Done():
//log
default:
e.replyTo <- result
}
}
}
// Web handler
http.HandleFunc("/bar", func(w http.ResponseWriter, r *http.Request) {
//decode request etc
...
replyTo := make(chan interface{}, 1)
ctx, cancel := context.WithCancel(context.BackGround())
event <- Event{req: req, ctx: ctx, replyTo: replyTo}
select{
case <-time.After(time.Second):
cancel()
//return 500
case r := <-replyTo:
// return some response
}
})
I do see that there is one single go-routine at the end, so parallelism is lost but I am okay with it.
Is this pattern the right way of doing this?
What other approaches can be suggested?
go
|
show 2 more comments
I am writing a web application where I have a long running goroutine.
I want to delegate all HTTP requests to this goroutine via channels.
The pattern that I have come across is:
// Internal long running goroutine
for{
select{
case e := <-event: //web request
req := e.req
// do something
....
select {
case <-ctx.Done():
//log
default:
e.replyTo <- result
}
}
}
// Web handler
http.HandleFunc("/bar", func(w http.ResponseWriter, r *http.Request) {
//decode request etc
...
replyTo := make(chan interface{}, 1)
ctx, cancel := context.WithCancel(context.BackGround())
event <- Event{req: req, ctx: ctx, replyTo: replyTo}
select{
case <-time.After(time.Second):
cancel()
//return 500
case r := <-replyTo:
// return some response
}
})
I do see that there is one single go-routine at the end, so parallelism is lost but I am okay with it.
Is this pattern the right way of doing this?
What other approaches can be suggested?
go
What are you trying to accomplish? Why not just usenet/http
?
– Flimzy
Nov 18 '18 at 8:48
I am using net/http... the handler function is delegating the work to goroutine which has data
– Saurav Prakash
Nov 18 '18 at 8:49
"Is this pattern the right way of doing this?" -- the right way of doing what? You still haven't explained your goal. Why go to all this effort to seemingly undermine the standard library, and make your code less efficient?
– Flimzy
Nov 18 '18 at 8:53
1
The handler function doesnt have enough state to handle request..It delegates it to another goroutine which has the required data procured from some other place. is that what you are trying to achieve?
– Shank
Nov 18 '18 at 8:55
@Shank Yes exactly
– Saurav Prakash
Nov 18 '18 at 8:57
|
show 2 more comments
I am writing a web application where I have a long running goroutine.
I want to delegate all HTTP requests to this goroutine via channels.
The pattern that I have come across is:
// Internal long running goroutine
for{
select{
case e := <-event: //web request
req := e.req
// do something
....
select {
case <-ctx.Done():
//log
default:
e.replyTo <- result
}
}
}
// Web handler
http.HandleFunc("/bar", func(w http.ResponseWriter, r *http.Request) {
//decode request etc
...
replyTo := make(chan interface{}, 1)
ctx, cancel := context.WithCancel(context.BackGround())
event <- Event{req: req, ctx: ctx, replyTo: replyTo}
select{
case <-time.After(time.Second):
cancel()
//return 500
case r := <-replyTo:
// return some response
}
})
I do see that there is one single go-routine at the end, so parallelism is lost but I am okay with it.
Is this pattern the right way of doing this?
What other approaches can be suggested?
go
I am writing a web application where I have a long running goroutine.
I want to delegate all HTTP requests to this goroutine via channels.
The pattern that I have come across is:
// Internal long running goroutine
for{
select{
case e := <-event: //web request
req := e.req
// do something
....
select {
case <-ctx.Done():
//log
default:
e.replyTo <- result
}
}
}
// Web handler
http.HandleFunc("/bar", func(w http.ResponseWriter, r *http.Request) {
//decode request etc
...
replyTo := make(chan interface{}, 1)
ctx, cancel := context.WithCancel(context.BackGround())
event <- Event{req: req, ctx: ctx, replyTo: replyTo}
select{
case <-time.After(time.Second):
cancel()
//return 500
case r := <-replyTo:
// return some response
}
})
I do see that there is one single go-routine at the end, so parallelism is lost but I am okay with it.
Is this pattern the right way of doing this?
What other approaches can be suggested?
go
go
edited Nov 18 '18 at 8:47
Flimzy
37.5k96496
37.5k96496
asked Nov 18 '18 at 8:12
Saurav PrakashSaurav Prakash
1249
1249
What are you trying to accomplish? Why not just usenet/http
?
– Flimzy
Nov 18 '18 at 8:48
I am using net/http... the handler function is delegating the work to goroutine which has data
– Saurav Prakash
Nov 18 '18 at 8:49
"Is this pattern the right way of doing this?" -- the right way of doing what? You still haven't explained your goal. Why go to all this effort to seemingly undermine the standard library, and make your code less efficient?
– Flimzy
Nov 18 '18 at 8:53
1
The handler function doesnt have enough state to handle request..It delegates it to another goroutine which has the required data procured from some other place. is that what you are trying to achieve?
– Shank
Nov 18 '18 at 8:55
@Shank Yes exactly
– Saurav Prakash
Nov 18 '18 at 8:57
|
show 2 more comments
What are you trying to accomplish? Why not just usenet/http
?
– Flimzy
Nov 18 '18 at 8:48
I am using net/http... the handler function is delegating the work to goroutine which has data
– Saurav Prakash
Nov 18 '18 at 8:49
"Is this pattern the right way of doing this?" -- the right way of doing what? You still haven't explained your goal. Why go to all this effort to seemingly undermine the standard library, and make your code less efficient?
– Flimzy
Nov 18 '18 at 8:53
1
The handler function doesnt have enough state to handle request..It delegates it to another goroutine which has the required data procured from some other place. is that what you are trying to achieve?
– Shank
Nov 18 '18 at 8:55
@Shank Yes exactly
– Saurav Prakash
Nov 18 '18 at 8:57
What are you trying to accomplish? Why not just use
net/http
?– Flimzy
Nov 18 '18 at 8:48
What are you trying to accomplish? Why not just use
net/http
?– Flimzy
Nov 18 '18 at 8:48
I am using net/http... the handler function is delegating the work to goroutine which has data
– Saurav Prakash
Nov 18 '18 at 8:49
I am using net/http... the handler function is delegating the work to goroutine which has data
– Saurav Prakash
Nov 18 '18 at 8:49
"Is this pattern the right way of doing this?" -- the right way of doing what? You still haven't explained your goal. Why go to all this effort to seemingly undermine the standard library, and make your code less efficient?
– Flimzy
Nov 18 '18 at 8:53
"Is this pattern the right way of doing this?" -- the right way of doing what? You still haven't explained your goal. Why go to all this effort to seemingly undermine the standard library, and make your code less efficient?
– Flimzy
Nov 18 '18 at 8:53
1
1
The handler function doesnt have enough state to handle request..It delegates it to another goroutine which has the required data procured from some other place. is that what you are trying to achieve?
– Shank
Nov 18 '18 at 8:55
The handler function doesnt have enough state to handle request..It delegates it to another goroutine which has the required data procured from some other place. is that what you are trying to achieve?
– Shank
Nov 18 '18 at 8:55
@Shank Yes exactly
– Saurav Prakash
Nov 18 '18 at 8:57
@Shank Yes exactly
– Saurav Prakash
Nov 18 '18 at 8:57
|
show 2 more comments
1 Answer
1
active
oldest
votes
Is this pattern the right way of doing this?
Assuming you are trying to manage where state in a single go routine, I would say no. I think it would be better to have some form of a state manager that is responsible for thread safety. Therefore the handler should take in something that can manage the state and simply expose a few methods to the handler.
type State interface{
Load() (string, error)
Save(something string) error
}
Decoupling the code will pay off for you later on. It will also allow unit tests for both the handler and the State that can be focused and readable.
Doesn't the channel guarantee thread safety? The channel is being read by 1 single goroutine and hence at any point of time, it would service a single request.
– Saurav Prakash
Nov 18 '18 at 9:21
Yes it can. However my point is that the pattern of having the handler take on thread safety is not great decoupling of concerns. If later you decide the channels are non-performant, you would want the ability to refactor without having to rewrite every single part.
– poy
Nov 18 '18 at 9:25
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53359006%2fpattern-for-handling-http-requests-via-channels%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
Is this pattern the right way of doing this?
Assuming you are trying to manage where state in a single go routine, I would say no. I think it would be better to have some form of a state manager that is responsible for thread safety. Therefore the handler should take in something that can manage the state and simply expose a few methods to the handler.
type State interface{
Load() (string, error)
Save(something string) error
}
Decoupling the code will pay off for you later on. It will also allow unit tests for both the handler and the State that can be focused and readable.
Doesn't the channel guarantee thread safety? The channel is being read by 1 single goroutine and hence at any point of time, it would service a single request.
– Saurav Prakash
Nov 18 '18 at 9:21
Yes it can. However my point is that the pattern of having the handler take on thread safety is not great decoupling of concerns. If later you decide the channels are non-performant, you would want the ability to refactor without having to rewrite every single part.
– poy
Nov 18 '18 at 9:25
add a comment |
Is this pattern the right way of doing this?
Assuming you are trying to manage where state in a single go routine, I would say no. I think it would be better to have some form of a state manager that is responsible for thread safety. Therefore the handler should take in something that can manage the state and simply expose a few methods to the handler.
type State interface{
Load() (string, error)
Save(something string) error
}
Decoupling the code will pay off for you later on. It will also allow unit tests for both the handler and the State that can be focused and readable.
Doesn't the channel guarantee thread safety? The channel is being read by 1 single goroutine and hence at any point of time, it would service a single request.
– Saurav Prakash
Nov 18 '18 at 9:21
Yes it can. However my point is that the pattern of having the handler take on thread safety is not great decoupling of concerns. If later you decide the channels are non-performant, you would want the ability to refactor without having to rewrite every single part.
– poy
Nov 18 '18 at 9:25
add a comment |
Is this pattern the right way of doing this?
Assuming you are trying to manage where state in a single go routine, I would say no. I think it would be better to have some form of a state manager that is responsible for thread safety. Therefore the handler should take in something that can manage the state and simply expose a few methods to the handler.
type State interface{
Load() (string, error)
Save(something string) error
}
Decoupling the code will pay off for you later on. It will also allow unit tests for both the handler and the State that can be focused and readable.
Is this pattern the right way of doing this?
Assuming you are trying to manage where state in a single go routine, I would say no. I think it would be better to have some form of a state manager that is responsible for thread safety. Therefore the handler should take in something that can manage the state and simply expose a few methods to the handler.
type State interface{
Load() (string, error)
Save(something string) error
}
Decoupling the code will pay off for you later on. It will also allow unit tests for both the handler and the State that can be focused and readable.
edited Nov 18 '18 at 9:39
Flimzy
37.5k96496
37.5k96496
answered Nov 18 '18 at 9:16
poypoy
6,43763364
6,43763364
Doesn't the channel guarantee thread safety? The channel is being read by 1 single goroutine and hence at any point of time, it would service a single request.
– Saurav Prakash
Nov 18 '18 at 9:21
Yes it can. However my point is that the pattern of having the handler take on thread safety is not great decoupling of concerns. If later you decide the channels are non-performant, you would want the ability to refactor without having to rewrite every single part.
– poy
Nov 18 '18 at 9:25
add a comment |
Doesn't the channel guarantee thread safety? The channel is being read by 1 single goroutine and hence at any point of time, it would service a single request.
– Saurav Prakash
Nov 18 '18 at 9:21
Yes it can. However my point is that the pattern of having the handler take on thread safety is not great decoupling of concerns. If later you decide the channels are non-performant, you would want the ability to refactor without having to rewrite every single part.
– poy
Nov 18 '18 at 9:25
Doesn't the channel guarantee thread safety? The channel is being read by 1 single goroutine and hence at any point of time, it would service a single request.
– Saurav Prakash
Nov 18 '18 at 9:21
Doesn't the channel guarantee thread safety? The channel is being read by 1 single goroutine and hence at any point of time, it would service a single request.
– Saurav Prakash
Nov 18 '18 at 9:21
Yes it can. However my point is that the pattern of having the handler take on thread safety is not great decoupling of concerns. If later you decide the channels are non-performant, you would want the ability to refactor without having to rewrite every single part.
– poy
Nov 18 '18 at 9:25
Yes it can. However my point is that the pattern of having the handler take on thread safety is not great decoupling of concerns. If later you decide the channels are non-performant, you would want the ability to refactor without having to rewrite every single part.
– poy
Nov 18 '18 at 9:25
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53359006%2fpattern-for-handling-http-requests-via-channels%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
What are you trying to accomplish? Why not just use
net/http
?– Flimzy
Nov 18 '18 at 8:48
I am using net/http... the handler function is delegating the work to goroutine which has data
– Saurav Prakash
Nov 18 '18 at 8:49
"Is this pattern the right way of doing this?" -- the right way of doing what? You still haven't explained your goal. Why go to all this effort to seemingly undermine the standard library, and make your code less efficient?
– Flimzy
Nov 18 '18 at 8:53
1
The handler function doesnt have enough state to handle request..It delegates it to another goroutine which has the required data procured from some other place. is that what you are trying to achieve?
– Shank
Nov 18 '18 at 8:55
@Shank Yes exactly
– Saurav Prakash
Nov 18 '18 at 8:57