Skip to content

Commit

Permalink
🐎 Query efficiency (#242)
Browse files Browse the repository at this point in the history
  • Loading branch information
shnizzedy authored Dec 9, 2019
2 parents 29d9f33 + adc207b commit bafaff8
Show file tree
Hide file tree
Showing 18 changed files with 738 additions and 717 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ Changes
-------
Unreleased
==========
2019-12-05: v0.7.1
^^^^^^^^^^^^^^^^^^
* :racehorse: Resolve some query efficiency problems
* :fire: :books: Remove some deprecated text and illustrations from README

2019-11-25: v0.6.6
^^^^^^^^^^^^^^^^^^
* :ambulance: Fix `POST response/applet/activity` route
Expand Down
81 changes: 0 additions & 81 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -87,83 +87,6 @@ Data Structure
**Girder for MindLogger** uses `reprolib <https://github.com/ReproNim/schema-standardization>`_ and has the following underlying data structure:
*Note: This project is still in version 0 and these descriptions and diagrams may sometimes diverge from the actual data structure as we develop.*

Diagram
#######
|ERD|
The above `entity-relationship diagram <https://cacoo.com/blog/er-diagrams-vs-eer-diagrams-whats-the-difference/>`_ was created with `dia 0.97+git <https://live.gnome.org/Dia>`_.

Glossary
########

Activity
^^^^^^^^
An "individual assessment", as defined in `reprolib <https://github.com/ReproNim/schema-standardization/tree/0fb4abd67d209e76325e6f42d428d7c275252ec6#20-need-for-standardizing-assessments>`_:`Activity <https://raw.githubusercontent.com/ReproNim/schema-standardization/master/schemas/Activity>`_.

Activity Set
^^^^^^^^^^^^
A "collection[…] of `activities <#activity>`_ as defined in `reprolib <https://github.com/ReproNim/schema-standardization/tree/0fb4abd67d209e76325e6f42d428d7c275252ec6#20-need-for-standardizing-assessments>`_:`ActivitySet <https://raw.githubusercontent.com/ReproNim/schema-standardization/master/schemas/ActivitySet>`_.

Applet
^^^^^^
A document assigning one or more `activity sets <#activity-set>`_ to one or more `users <#user>`_ with or without scheduling and other constraints.

Applet-specific User ID
^^^^^^^^^^^^^^^^^^^^^^^
An identifier for a given `user <#user>`_ (or `reviewer <#reviewer>`_ or `subject <#subject>`_) for an `applet <#applet>`_ that does not expose that user's other data to anyone authorized to view information related to that applet.

Context
^^^^^^^
A set of rules for interpreting a JSON-LD document [from this database] as specified in The Context of the JSON-LD Syntax specification."

This definition comes from `JSON-LD 1.1 <https://json-ld.org/spec/latest/json-ld/>`_ `context <https://json-ld.org/spec/latest/json-ld/#dfn-contexts>`_.

Coordinator
^^^^^^^^^^^

Icon
^^^^

Illustration
^^^^^^^^^^^^

Manager
^^^^^^^
An individual responsible for setting schedules, `subjects <#subject>`_ and other constraints as well as inviting other managers, `users <#user>`_ and `reviewers <#reviewer>`_ to an `applet <#applet>`_.

Protected health information
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Any information about health status, provision of health care, or payment for health care that […] can be linked to a specific `individual <#user>`_.

This definition comes from the Wikipedia article `Protected health information <https://en.wikipedia.org/wiki/Protected_health_information>`_.

Response
^^^^^^^^
Data collected when a `user <#user>`_ responds to an `activity <#activity>`_.

Reviewer
^^^^^^^^
An individual authorized to review `user <#user>`_ `responses <#response>`_ to `activities <#activity>`_ in an `applet <#applet>`_.

Screen
^^^^^^
One or more "elements of individual assessments" displayed in a single screen or page view, as defined in `reprolib <https://github.com/ReproNim/schema-standardization/tree/0fb4abd67d209e76325e6f42d428d7c275252ec6#20-need-for-standardizing-assessments>`_:`Item <https://raw.githubusercontent.com/ReproNim/schema-standardization/master/schemas/Field>`_ and `Issue #85 <https://github.com/ReproNim/schema-standardization/issues/85>`_.

Skin
^^^^
Color scheme and other branding and appearance-related metadata.

Subject
^^^^^^^
The person being informed about by the `user <#user>`_ `responding <#response>`_ to an `activity <#activity>`_. For self-report, the same user as the informant.

Text
^^^^
Copy included in the mobile and web app, including "About MindLogger" and helper text.

User
^^^^
An individual using a MindLogger mobile application or MindLogger web application to `respond <#response>`_ to `activities <#activity>`_.

Links
-----
- `reprolib specification <https://github.com/ReproNim/schema-standardization>`_
Expand All @@ -187,10 +110,6 @@ For questions, comments, or to get in touch with the maintainers, head to their

We'd love for you to `contribute to Girder <CONTRIBUTING.rst>`_.

.. |ERD| image:: ./docs/images/Mindlogger-DB-ER.png
:alt: MindLogger database entity-relationship diagram
:target: ./docs/images/Mindlogger-DB-ER.dia

.. |logo| image:: ./girderformindlogger/web_client/src/assets/ML-logo_25px.png
:alt: Girder for MindLogger
:target: https://api.mindlogger.org
Expand Down
66 changes: 29 additions & 37 deletions girderformindlogger/api/v1/applet.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

import itertools
import re
import threading
import uuid
import requests
from ..describe import Description, autoDescribeRoute
Expand Down Expand Up @@ -162,36 +163,24 @@ def assignGroup(self, folder, group, role, subject):
)
def createApplet(self, protocolUrl=None, name=None, informant=None):
thisUser = self.getCurrentUser()
# get an activity set from a URL
protocol = ProtocolModel().getFromUrl(
protocolUrl,
'protocol',
thisUser,
refreshCache=False
)[0]
protocol = protocol.get('protocol', protocol)
# create an applet for it
applet=AppletModel().createApplet(
name=name if name is not None and len(name) else ProtocolModel(
).preferredName(
protocol
),
protocol={
'_id': 'protocol/{}'.format(protocol.get('_id')),
'url': protocol.get(
'meta',
{}
).get(
'protocol',
{}
).get('url', protocolUrl)
},
user=thisUser,
constraints={
'informantRelationship': informant
} if informant is not None else None
thread = threading.Thread(
target=AppletModel().createAppletFromUrl,
kwargs={
'name': name,
'protocolUrl': protocolUrl,
'user': thisUser,
'constraints': {
'informantRelationship': informant
} if informant is not None else None
}
)
return(applet)
thread.start()
return({
"message": "The applet is being created. Please check back in "
"several mintutes to see it. If you have an email "
"address associated with your account, you will receive "
"an email when your applet is ready."
})

@access.user(scope=TokenScope.DATA_WRITE)
@autoDescribeRoute(
Expand Down Expand Up @@ -239,8 +228,6 @@ def updateInformant(self, applet, informant):
.errorResponse('Write access was denied for this applet.', 403)
)
def deactivateApplet(self, folder):
import threading

applet = folder
user = Applet().getCurrentUser()
applet['meta']['applet']['deleted'] = True
Expand All @@ -251,8 +238,10 @@ def deactivateApplet(self, folder):
applet.get('_id')
)
thread = threading.Thread(
target=AppletModel().updateAllUserCaches(applet, user)
target=AppletModel().updateUserCacheAllUsersAllRoles,
args=(applet, user)
)
thread.start()
else:
message = 'Could not deactivate applet {} ({}).'.format(
AppletModel().preferredName(applet),
Expand All @@ -264,7 +253,12 @@ def deactivateApplet(self, folder):
@access.user(scope=TokenScope.DATA_READ)
@autoDescribeRoute(
Description('Get an applet by ID.')
.modelParam('id', model=AppletModel, level=AccessType.READ)
.modelParam(
'id',
model=AppletModel,
level=AccessType.READ,
destName='applet'
)
.param(
'refreshCache',
'Reparse JSON-LD',
Expand All @@ -274,8 +268,7 @@ def deactivateApplet(self, folder):
.errorResponse('Invalid applet ID.')
.errorResponse('Read access was denied for this applet.', 403)
)
def getApplet(self, folder, refreshCache=False):
applet = folder
def getApplet(self, applet, refreshCache=False):
user = self.getCurrentUser()
return(
jsonld_expander.formatLdObject(
Expand Down Expand Up @@ -414,8 +407,7 @@ def invite(self, applet, role="user", idCode=None, profile=None):
.errorResponse('Read access was denied for this applet.', 403)
)
def setConstraints(self, folder, activity, schedule, **kwargs):
import threading
thisUser = Applet().getCurrentUser()
thisUser = self.getCurrentUser()
applet = jsonld_expander.formatLdObject(
_setConstraints(folder, activity, schedule, thisUser),
'applet',
Expand Down
2 changes: 1 addition & 1 deletion girderformindlogger/api/v1/protocol.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def __init__(self):
def getProtocol(self, folder):
try:
protocol = folder
user = Protocol().getCurrentUser()
user = self.getCurrentUser()
return(
jsonld_expander.formatLdObject(
protocol,
Expand Down
2 changes: 1 addition & 1 deletion girderformindlogger/api/v1/screen.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ def __init__(self):
.errorResponse('Read access was denied for the screen.', 403)
)
def createScreen(self, activity, screenName=None):
thisUser = Screen().getCurrentUser()
thisUser = self.getCurrentUser()
activity = ActivityModel().load(
activity,
level=AccessType.WRITE,
Expand Down
Loading

0 comments on commit bafaff8

Please sign in to comment.