I am coding a custom solution and made some progress but now ran into an issue. My current approach is this:
For each real project, i created a “shadow” project. If a task is created, modified or deleted in the real project, a respective “shadow task” in the “shadow project” is synced. All tasks in this “shadow project” are automatically assigned to a dummy user which is then used for the reporting.
I succeed in making an initial sync from the real project to the shadow project by getting all tasks in the real project, duplicating them, renaming them with a _shadow suffix, moving them to the shadow project and assigning the dummy user. So far so good.
Now i need to keep the shadow project in sync with the real project if a user changes something there. For example if the user creates a task in the real project, i listen to the events and then if i catch the create event, i also create a matching task in the shadow project.
I ran into a problem when a user deletes a task in the real project. I catch the delete event with the event handler and extract the gid of the deleted task. I then need to find the matching task in the shadow project to also delete it.
My first approach was that every real task had the shadow listed as a dependent so i could now which shadow task belongs to which real task. I used the get dependent function:
GET /tasks/{task_gid}/dependents
The issue is that when i call that function upon receiving the delete event for that task, this task has obviously already been deleted and the call fails.
I need a way to find/identify always the corresponding shadow task of a real task if some action is performed on the real task. I need a link from the real task to it’s shadow to keep the shadow in sync.
I haven’t found a satisfying solution and want to ask if you know any good approach?
I thought about using the “Search tasks in a workspace function” and tried it but couldn’t get it to work as i want. I had two ideas on how to use it:
-
I created a section in the shadow project for each duplicated task which had the original task’s gid as a name string. I would then use the search function to get this section in the shadow project and have access to it’s tasks. But this didnt work, i suspect the search function can only find sections by their gid and not by their displayed name string?
-
I could create a custom field in each shadow task which has the gid of the original task in it and then use the search function to get the shadow task with the right gid string value in this custom field. I am still thinking about this solution but i feel there must be an easier way.
So in a nutshell, how can i have this lookup function between the real task and its separate shadow task that i can always find the shadow task when something in the real task?
Thankful for any ideas and possible approaches. I can also post code more snippets if anything is unclear.
My small event handler looks like this:
print("starting streaming events for project \r\n")
for event in client.events.get_iterator({'resource': project_gids['proj_wow_sc']}):
#print("event", event, end='\r\n\n')
event_type = event['type']
action = event['action']
print("Action:", action, "Event type:", event_type, end='\r\n')
# if the event has the task type, we need to change something in the shadow project
if event_type == 'task':
# if delete task, delete dependents from shadow
if action == 'deleted':
try:
# Try to find the task
search_task_result = client.tasks.search_tasks_for_workspace(GID_WORKSPACE, {'?sections.any': event['resource']['gid'], '?projects.any': project_gids['proj_wow_sc_shadow']}, opt_pretty=USE_PRETTY_RESPONSE)
print(next(search_task_result))
'''
#get section of task, delete tasks in that section and delete section
print("Task",event['resource']['name'],"was", action, end='\r\n')
shadow_section_result = client.sections.get_section(event['resource']['gid'], {'param': 'value', 'param': 'value'}, opt_pretty=USE_PRETTY_RESPONSE)
print(shadow_section_result)
#shadow_section_result = client.tasks.get_tasks_for_section(event['resource']['gid'], {'param': 'value', 'param': 'value'}, opt_pretty=USE_PRETTY_RESPONSE)
'''
except KeyError:
print("Key not found", end='\r\n')
# if create task, create new task in shadow too
# if change task, change task in shadow too, or if change, delete shadow, create new shadow?