-
Notifications
You must be signed in to change notification settings - Fork 1k
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
add active_tasks for view builds using version stamps #3003
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A good start. I'm not familiar with how active_tasks works but I'm not sure this is the best approach. All the information you need for view progress is in the job info. So when a query for _active_tasks
is received I think you could just read the job queue and get all the information you need and then respond. Or is there more to this?
{type, indexer}, | ||
{database, Mrst#mrst.db_name}, | ||
{design_document, Mrst#mrst.idx_name}, | ||
{changes_done, 0}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will changes always be 0? What happens if an index is half-built and the indexer is starting up again?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't have a good solution to this. Mainly that the indexer process has to die first which means the active_task tuple is automatically removed from memory. I was thinking of writing a counter to fdb, but that opened up a new can of worms. The idea here is that is that each process will just own a portion of what they've indexed and not care about what's been done previously. In other words, if you have an index that built 900 documents out of a 1000 document db and it had to restart, it'll start from 0 and just get up to 100 for ChangesDone and finish.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Historically, changes_done
refers to how many changes have been processed by this view update. It's for judging how much work is left before the view is up to date. One way to think of this would be if you had a 10,000,000 docs processed for a view, and then went to process another 1,000,000 docs to bring the view up to date, you wouldn't want to start at 99% finished as that'd be misleading to operators.
Agree with @garrensmith, for reporting the job on all the nodes, it might be easier to think of something like this:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks fine to me. I'm not sure whether we should try and compare the version stamps to give a rough approximation of the progress completed. I think for now it would be fine and if/when fdb gets a count_rows_betwee_keys
we can replace it with something more accurate. I'm not sure if I want to require that or merely suggest so will wait for feedback on my feedback before approving.
5b9c90b
to
c9c8767
Compare
c9c8767
to
59e1acb
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is looking much better. Nice work. Could you check if we have any elixir active tasks tests and make sure they are run with make check
. It might be worth adding a few eunit tests around the changes_doc etc.
|
||
|
||
active_tasks_info(ChangesDone, DbName, DDocId, LastSeq, DBSeq) -> | ||
VS = case LastSeq of |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't like storing all this active task info in the job. All of this can be generated when CouchDB receive's a _active_tasks
request. If we keep adding more and more information to the job info means we running the risk of exceeding the FDB value limit. Rather just add the current_version_stamp
and db_version_stamp
to the job options. Is indexer_pid
actually useful? What would a user do with that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The reason I had thought of it is that for replication tasks, for example, we we'd have to know to introspect a few other places specific to replicator to add "source", "target", etc. So active tasks would have to start knowing about how to extract fields from various applications. Perhaps we'd want a simple registration like we have for indices in fabric2_index: https://github.com/apache/couchdb/blob/prototype/fdb-layer/src/fabric/src/fabric2_index.erl#L51-L53 - modules (applications) register a callback for _active_tasks handler and call it when building the response? Or, perhaps we can do that as round 2 if we see the values getting close to 100KB size.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@garrensmith @nickva how about leaving just changes_done
to the job_data and then computing the rest on the fly? It seems we should be adding an entirely new fabric_active_tasks module which allows the extractions to reside in there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That sounds good.
366a3c6
to
c009825
Compare
@tonysun83 looks better! Good improvement. I made a few comments-in line. One part that I am not sure if it is worth starting two transactions per task item just to compute version stamps and maybe a few other fields. That seems quite expensive if, say, someone is polling status on a cluster with hundreds of tasks, given that jobs already have the dbs open and all that data available to start with. The reason we decided to do that was to ensure we are below 100KB for JobData, I think? We'd have to make a convincing case that our active_jobs status section in each JobData would have a chance of pushing it over the 100KB value limit. I tried encoding a large-ish object similar to the one we are adding for the task status:
So we'd be adding at most another 1KB (in the worst case) to get closer to the 100KB limit if we save the status in the job data that doesn't seem that bad perhaps and it would simplify the design quite a bit more. |
I'm actually counting three possible transactions between opening the database if its not in cache, one for the reading the design doc, then one for the other two bits of info. Can someone point me to the discussion where we decided to move away from storing active task info in the job state? I'm not seeing how this is a better approach or why the job state approach is unworkable. |
@davisp : Here was @garrensmith 's concern #3003 (comment). But I think I found a compromise and pushed (now the populate_tasks function is way simpler without the reads). We really just need to add two new items to the JobData info: <<"changes_done">> and <<"db_seq">> |
@tonysun83 The history of this PR is super confusing to me. The last update appears to have reverted to storing all of the info back in the job state which means that this new populate_active_tasks is just "format_job_as_active_task". Which is fine I suppose. Though it seems like it'd be a lot more straightforward for the jobs to just store what they want their active_task output to look like in the first place? Adding a whole registration/callback system for this seems much more complex than the original plan to just spit out the job data as JSON. |
@davisp: agreed that it's gotten way more complex. I think @nickva thought that the registration callback would help with the sizing issue, and as a side benefit, add flexibility for future |
@tonysun83: Agree with @davisp, it's not worth having the registration system just for this. We could still hide the
And use the original design #3003 (comment)
The registration would have helped with encapsulation, if we had a size issue and had to compute the section on the fly to avoid the http handle hard-coding knowledge about the replication and indexing apps. But I think we determined computing on the fly was not as optimal, and it wasn't adding that much more to the job data size. If we ever do need to compute it on the fly, we could also come back add the complexity later. |
19856c5
to
0e72743
Compare
@nickva addressed your latest comments and added a test. Will add more tests later and then rebase with a proper commit history. |
src/couch_jobs/src/couch_jobs.erl
Outdated
|
||
-spec get_types(jtx()) -> [job_type()] | {error, any()}. | ||
get_types(Tx) -> | ||
couch_jobs_fdb:tx(couch_jobs_fdb:get_jtx(Tx), fun(JTx) -> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor nit: I think it's a 5 space indent instead of 4
@tonysun83 looks great! awesome work. Just a few minor nits, whitespace and indents and such |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is looking really good. I've left a note about the extra active task info. I'm still not sure why we need to have all of that in the job data.
[{[{node,Node} | Task]} || Task <- Tasks] | ||
end, Replies), | ||
send_json(Req, lists:sort(Response)); | ||
ActiveTasks = fabric2_active_tasks:get_active_tasks(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome. This is great.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice work. This looks great.
|
||
|
||
update_active_task_info(JobData, ActiveTaskInfo) -> | ||
JobData#{?ACTIVE_TASK_INFO => ActiveTaskInfo}. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tiny nit: 5 indent instead of 4, add a newline at the end of the file as well, just for so GH diff doesn't show the red warning :-P
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh, I thought I changed this. weird. thx
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 Nice work, Tony!
Made a small comment about an indent. Run the new files through emillio, make sure it's happy in case we missed some formatting issues.
Then don't forget to squash some commits, maybe group them into 2 or 3, something like below or whatever looks better to you:
- couch_jobs API additions
- fabric2 + chttpd part
- couch_views bits
f1b261e
to
4505f4d
Compare
We expose get_types in couch_jobs and also add get_active_jobs_ids to get the active job ids given a certain type.
Instead of relying on couch_task_status, we use fabric2_active_tasks to construct active_task info via couch_jobs.
Active Tasks requires TotalChanges and ChangesDone to show the progress of long running tasks. This requires count_changes_since to be implemented. Unfortunately, that is not easily done via with foundationdb. This commit replaces TotalChanges with the versionstamp + the number of docs as a progress indicator. This can possibly break existing api that relys on TotalChanges. ChangesDone will still exist, but instead of relying on the current changes seq it is simply a reflection of how many documents were written by the updater process.
4505f4d
to
a447f07
Compare
Overview
Active Tasks requires TotalChanges and ChangesDone to show the progress
of long running tasks. This requires
count_changes_since/2
to beimplemented. Unfortunately, that is not easily done with
foundationdb. This commit replaces TotalChanges with the
versionstamp + the number of docs as a progress indicator. This can
possibly break existing api that relys on TotalChanges. ChangesDone
will still exist, but instead of relying on the current changes seq
it is simply a reflection of how many documents were written by the
updater process.
The new responses look like this:
Note that this only shows one process. IIUC, we can have multiple workers indexing in parallel. I think this approach also takes care of this with the ChangesDone only reflecting how many documents have been indexed for that range.
Testing recommendations
Tests need to be added. If this approach is accepted, I will add more precise tests. Currently ran manual tests.
Related Issues or Pull Requests
Checklist
rel/overlay/etc/default.ini