Exemple #1
0
def worker_function(event_type,
                    assignment_id,
                    participant_id,
                    node_id=None,
                    details=None):
    """Process the notification."""
    _config()
    q = _get_queue()
    try:
        db.logger.debug("rq: worker_function working on job id: %s",
                        get_current_job().id)
        db.logger.debug("rq: Received Queue Length: %d (%s)", len(q),
                        ", ".join(q.job_ids))
    except AttributeError:
        db.logger.debug("Debug worker_function called synchronously")

    exp = _loaded_experiment(db.session)
    key = "-----"

    exp.log(
        "Received an {} notification for assignment {}, participant {}".format(
            event_type, assignment_id, participant_id),
        key,
    )

    if event_type == "TrackingEvent":
        node = None
        if node_id:
            node = models.Node.query.get(node_id)
        if not node:
            participant = None
            if participant_id:
                # Lookup assignment_id to create notifications
                participant = models.Participant.query.get(participant_id)
            elif assignment_id:
                participants = models.Participant.query.filter_by(
                    assignment_id=assignment_id).all()
                # if there are one or more participants select the most recent
                if participants:
                    participant = max(participants,
                                      key=attrgetter("creation_time"))
                    participant_id = participant.id
            if not participant:
                exp.log(
                    "Warning: No participant associated with this "
                    "TrackingEvent notification.",
                    key,
                )
                return
            nodes = participant.nodes()
            if not nodes:
                exp.log(
                    "Warning: No node associated with this "
                    "TrackingEvent notification.",
                    key,
                )
                return
            node = max(nodes, key=attrgetter("creation_time"))

        if not details:
            details = {}
        info = information.TrackingEvent(origin=node, details=details)
        db.session.add(info)
        db.session.commit()
        return

    runner_cls = WorkerEvent.for_name(event_type)
    if not runner_cls:
        exp.log(
            "Event type {} is not supported... ignoring.".format(event_type))
        return

    if assignment_id is not None:
        # save the notification to the notification table
        notif = models.Notification(assignment_id=assignment_id,
                                    event_type=event_type)
        db.session.add(notif)
        db.session.commit()

        # try to identify the participant
        participants = models.Participant.query.filter_by(
            assignment_id=assignment_id).all()

        # if there are one or more participants select the most recent
        if participants:
            participant = max(participants, key=attrgetter("creation_time"))

        # if there are none print an error
        else:
            exp.log(
                "Warning: No participants associated with this "
                "assignment_id. Notification will not be processed.",
                key,
            )
            return None

    elif participant_id is not None:
        participant = models.Participant.query.filter_by(
            id=participant_id).all()[0]
    else:
        raise ValueError(
            "Error: worker_function needs either an assignment_id or a "
            "participant_id, they cannot both be None")

    participant_id = participant.id

    runner = runner_cls(participant, assignment_id, exp, db.session, _config(),
                        datetime.now())
    runner()
    db.session.commit()
Exemple #2
0
def worker_function(event_type, assignment_id, participant_id):
    """Process the notification."""
    try:
        db.logger.debug("rq: worker_function working on job id: %s",
                        get_current_job().id)
        db.logger.debug('rq: Received Queue Length: %d (%s)', len(q),
                        ', '.join(q.job_ids))
    except AttributeError:
        db.logger.debug('Debug worker_function called synchronously')

    exp = Experiment(session)
    key = "-----"

    exp.log(
        "Received an {} notification for assignment {}, participant {}".format(
            event_type, assignment_id, participant_id), key)

    if assignment_id is not None:
        # save the notification to the notification table
        notif = models.Notification(assignment_id=assignment_id,
                                    event_type=event_type)
        session.add(notif)
        session.commit()

        # try to identify the participant
        participants = models.Participant.query\
            .filter_by(assignment_id=assignment_id)\
            .all()

        # if there are one or more participants select the most recent
        if participants:
            participant = max(participants, key=attrgetter('creation_time'))

        # if there are none print an error
        else:
            exp.log(
                "Warning: No participants associated with this "
                "assignment_id. Notification will not be processed.", key)
            return None

    elif participant_id is not None:
        participant = models.Participant.query\
            .filter_by(id=participant_id).all()[0]
    else:
        raise ValueError(
            "Error: worker_function needs either an assignment_id or a "
            "participant_id, they cannot both be None")

    participant_id = participant.id

    if event_type == 'AssignmentAccepted':
        pass

    elif event_type == 'AssignmentAbandoned':
        if participant.status == "working":
            participant.end_time = datetime.now()
            participant.status = "abandoned"
            exp.assignment_abandoned(participant=participant)

    elif event_type == 'AssignmentReturned':
        if participant.status == "working":
            participant.end_time = datetime.now()
            participant.status = "returned"
            exp.assignment_returned(participant=participant)

    elif event_type == 'AssignmentSubmitted':
        if participant.status in ["working", "returned", "abandoned"]:
            participant.end_time = datetime.now()
            participant.status = "submitted"
            session.commit()

            # Approve the assignment.
            exp.recruiter().approve_hit(assignment_id)
            participant.base_pay = config.get('base_payment')

            # Check that the participant's data is okay.
            worked = exp.data_check(participant=participant)

            # If it isn't, fail their nodes and recruit a replacement.
            if not worked:
                participant.status = "bad_data"
                exp.data_check_failed(participant=participant)
                session.commit()
                exp.recruiter().recruit(n=1)
            else:
                # If their data is ok, pay them a bonus.
                # Note that the bonus is paid before the attention check.
                bonus = exp.bonus(participant=participant)
                participant.bonus = bonus
                if bonus >= 0.01:
                    exp.log("Bonus = {}: paying bonus".format(bonus), key)
                    exp.recruiter().reward_bonus(assignment_id, bonus,
                                                 exp.bonus_reason())
                else:
                    exp.log("Bonus = {}: NOT paying bonus".format(bonus), key)

                # Perform an attention check.
                attended = exp.attention_check(participant=participant)

                # If they fail the attention check, fail nodes and replace.
                if not attended:
                    exp.log("Attention check failed.", key)
                    participant.status = "did_not_attend"
                    exp.attention_check_failed(participant=participant)
                    session.commit()
                    exp.recruiter().recruit(n=1)
                else:
                    # All good. Possibly recruit more participants.
                    exp.log("All checks passed.", key)
                    participant.status = "approved"
                    exp.submission_successful(participant=participant)
                    session.commit()
                    exp.recruit()

    elif event_type == "NotificationMissing":
        if participant.status == "working":
            participant.end_time = datetime.now()
            participant.status = "missing_notification"

    elif event_type == "AssignmentReassigned":
        participant.end_time = datetime.now()
        participant.status = "replaced"
        exp.assignment_reassigned(participant=participant)

    else:
        exp.log("Error: unknown event_type {}".format(event_type), key)

    session.commit()