+import logging
+import time
+
+from django.db import transaction
+from django.utils.timezone import now
+
+from pyqcg.service import Registry
+from pyqcg.utils import Credential, TimePeriod
+
+
+logger = logging.getLogger(__name__)
+
+
+@transaction.atomic
+def update_user_data(user, proxy):
+ ts = time.time()
+ from qcg.models import User, Job, Task, Allocation, NodeInfo
+
+ credential = Credential(proxy)
+ registry = Registry(credential)
+
+ # put lock on user record (hopefully..?)
+ user = User.objects.select_for_update().get(pk=user.pk)
+
+ changed_filter = {'changed': TimePeriod(after=user.last_update)}
+
+ ###################################
+ # Jobs
+ ###################################
+ jts = time.time()
+ jobs = registry.jobs(**changed_filter)
+ jte = time.time()
+
+ jobs_count = 0
+ for qcg_job in jobs:
+ params = Job.qcg_map(qcg_job, user)
+ job_id = params.pop('job_id')
+
+ Job.objects.update_or_create(job_id=job_id, defaults=params)
+ jobs_count += 1
+
+ ###################################
+ # Tasks
+ ###################################
+ tts = time.time()
+ tasks = registry.tasks(**changed_filter)
+ tte = time.time()
+
+ jobs_cache = {j.job_id: j for j in Job.objects.filter(owner=user)}
+ task_count = 0
+ for qcg_task in tasks:
+ params = Task.qcg_map(qcg_task, jobs_cache)
+ task_id = params.pop('task_id')
+
+ task, created = Task.objects.update_or_create(job__job_id=qcg_task.job_id, task_id=task_id, defaults=params)
+
+ if not created:
+ task.allocations.all().delete()
+
+ for qcg_alloc in qcg_task.allocations:
+ alloc = task.allocations.create(**Allocation.qcg_map(qcg_alloc))
+
+ for qcg_node in qcg_alloc.nodes:
+ alloc.nodes.create(**NodeInfo.qcg_map(qcg_node))
+
+ task_count += 1
+
+ # release user lock
+ user.last_update = now()
+ user.save()
+
+ elapsed = time.time() - ts
+ elapsed_jobs = jte - jts
+ elapsed_tasks = tte - tts
+ elapsed_py = elapsed - elapsed_jobs - elapsed_tasks
+ logger.info('(%.3f) USER = %s, JOBS = %s (%.3f), TASKS = %s (%.3f), TIME = %.3f',
+ elapsed, user, jobs_count, elapsed_jobs, task_count, elapsed_tasks, elapsed_py)