-
Notifications
You must be signed in to change notification settings - Fork 3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Defragment framework interfaces into context based calls #107
Comments
@xiang90 @xiaoyunwu |
"In FlagMetaToX, it prepended epoch to the string and set it in etcd." |
meritop/framework/bootstrap.go Line 231 in 7e62eb3
|
More about the "epoch-meta":
|
ok, I got it, you mean the epoch is in meta, which is in etcd. But I still do not understand why we have issues in Can you show a list of event that problem will arise? What if we prepend the epoch info to req in the framework, so that we know which epoch is this request about? Basically doing the same thing like we did to meta. |
Request has epoch. In spirit of #101 , we add epoch to all communication between frameworks.
This is user API. User didn't add epoch to the meta. We need to separate framework and task layers. See my Analysis section at the top. |
I know, user call our framework with req, in our implementation we prepend epcoh, before we return result, we take out epcoh from req, that way, user do not have to know anything, but we have info we need to do the right thing. |
That's right. That's why I am proposing to give context to user and that context carries epoch, etc. info. |
but can we encode context into req then take it out? On Thu, Jan 15, 2015 at 5:16 PM, Hongchao Deng [email protected]
|
There are many choices to give context to user:
It's decision making. I only care letting user call APIs in this way. There is one more important thing to discuss: what should be called via Context not Framework? My list:
|
So u do not think pretend epoch would work? |
I didn't catch your question.. Could you use example? |
I think we should stay in simple if possible, what do u think? |
Do you have simpler solution for this? |
My preference is that we encoding the context into req and also response, Otherwise, we have to again explain what is context, and how to use it. On the separate note, I am wondering whether we can use the following where ByteSink type ByteSink interface{ this way the application can get access to the raw data stream directly, We can also make // These are payload for application purpose. Xiaoyun On Thu, Jan 15, 2015 at 5:23 PM, Hongchao Deng [email protected]
|
Let's talk with examples. Let's assume we have encoded context into req: func (t *dummySlave) ParentDataReady(parentID uint64, req Request, resp Resp) {
...
if len(children) != 0 {
req.Context.FlagMetaToChild("ParamReady")
} else {
req.Context.FlagMetaToParent("GradientReady")
}
} So my question is, what APIs should be included in Context not Framework? My list:
|
Is it possible to do away with the concept of context? I still believe we can handle it without task implementation ever know Xiaoyun On Thu, Jan 15, 2015 at 6:37 PM, Hongchao Deng [email protected]
|
See my analysis section and first paragraph in solution section. Without context, there is no way between framework and task to determine whether they are talking in the same epoch. |
Ok, Let me try to sequence it in a way that makes sense. in epoch 6, task implementation says: before framework.FlagMetaToX executed, in the function, the epoch 7 is encoded in FlagMetaToChild I agree with you that instantiate a new context for each epoch is good idea. But can it be a parameter instead of a type. |
What is the reason that we should include incEpoch in context? Here is my proposal: GetContext() Context Where Context is a opaque type that includes epoch id. in Context it supports the follow three functions: What do you guys think? |
Adding GetContext() in framework is the same thing of FlagMetaToChild().
I mentioned we need discussion on this. Currently I am fine only adding FlagMetaToX(). IncEpoch() in context indicates more explicit operation: we expected to increment at a specific epoch we know, not a global one user couldn't be sure. |
What I really mean is following. task implementation first get context from framework, that context then can Is this what you have in mind, if so, we are on the same page. On Fri, Jan 16, 2015 at 4:30 PM, Hongchao Deng [email protected]
|
No. Task get context from each callback method (i.e. DataReady, MetaReady, SetEpoch, etc.). Because it's during this communication between them that epoch shift might happen. |
Using a state pattern, let's introduce a state call Context. Slightly different from Hongchao's suggestion, I think we can get away with just state object with no method. So I take it that we both agree that the following method in framework can be changed into As suggested by Hongchao, we can pass context as parameter to all the task implementation callback functions: The fundamental reason for the current test failure is that we need to have a state machine inside task implementation which handle its event in the right order. But I think add this context is a reasonable thing to do. |
It's too complicated to have APIs like this: FlagMetaToParent(context Context, meta string)
FlagMetaToChild(context Context, meta string)
DataRequest(context Context, toID uint64, meta string) We shouldn't rely on user to pass in a context. It will only add burden of checking and complication. |
@fengjingchao How about using a generic context data struct? For example, an embed hash map? And we always attach Context to each request? Actually we can use this small lib for context and cancellation: |
/cc @xiaoyunwu Context is widely used in golang world. So we still can preserve the simplicity we want by not introducing "new" concepts. Actually this might also simplify the code by avoiding customized cancellation solution. |
Problem Description
The latest build failure was caused in the race:
In FlagMetaToX, it prepended epoch to the string and set it in etcd. However, the current implementation is wrong about synchronizing epoch here:
The problem is, a new epoch 7 was set, and it flagged meta with the epoch 7. But it's actually dealing with data in epoch 6!
Analysis
Apparently there are many ways to resolve it. We can stop all work on hand at the end of each epoch. But this is not code scalable -- if we write more remote requests, we also need to consistently close them, and heavy burden on debugging. Or we can just let user pass the epoch to
FlagMetaToChild
. This violates our design, and I am aware that keeping track of epoch, etc. info should be done in framework, not user level.Proposed Solution
After a second thought to framework interface, actually there are two types of work in it. One type is epoch specific: FlagMetaToX, DataRequest, (maybe) IncEpoch. The rest of APIs are the other type, epoch agnostic.
I propose to defragment FlagMetatoX, DataRequest into a different interface:
And change Task interface:
In this way, the context will help us track epoch and it's easy for use to synchronized them under the framework hood.
The text was updated successfully, but these errors were encountered: