示例#1
0
def add_youtube_photo(client_upload_id, storage_id, author, album, now, youtube_id):
    def get_next_album_index(album):
        album_index_q = Photo.objects.filter(album=album).aggregate(Max("album_index"))

        max_album_index = album_index_q["album_index__max"]
        if max_album_index is None:
            return 0
        else:
            return max_album_index + 1

    success = False
    while not success:
        try:
            with transaction.atomic():
                next_album_index = get_next_album_index(album)
                p, created = Photo.objects.get_or_create(
                    storage_id=storage_id,
                    defaults={
                        "photo_id": Photo.generate_photo_id(),
                        "media_type": Photo.MEDIA_TYPE_YOUTUBE,
                        "client_upload_id": client_upload_id,
                        "subdomain": Photo.choose_random_subdomain(),
                        "date_created": now,
                        "author": author,
                        "album": album,
                        "album_index": next_album_index,
                        "youtube_id": youtube_id,
                    },
                )
        except IntegrityError:
            # This will happen if there is a collision with a duplicate
            # 'album_index' from a concurrent request
            success = False
        else:
            success = True
    if created:
        if not in_testing_mode():
            # Update the photo servers:
            for photo_server in PhotoServer.objects.filter(subdomain=p.subdomain, unreachable=False):
                # TODO We should use concurrent requests for this

                num_retries = 5
                initial_retry_time = 4

                try:
                    request_with_n_retries(
                        num_retries,
                        initial_retry_time,
                        lambda: photo_server_set_photos(photo_server.photos_update_url, photo_server.auth_key, [p]),
                    )
                except requests.exceptions.RequestException:
                    # TODO Log this
                    photo_server.set_unreachable()

        album.save_revision(now, True)

        photos_added_to_album.send(sender=None, photos=[p.photo_id], by_user=author, to_album=album)
示例#2
0
    def add_photos_to_db(self, photo_ids):
        """
        Returns a dictionary from subdomain values to lists of Photo objects
        """
        added_photos = {}

        album = Album.objects.get(pk=self.album_id)
        album_index_q = Photo.objects.filter(album=album).aggregate(Max("album_index"))

        max_album_index = album_index_q["album_index__max"]
        if max_album_index is None:
            next_album_index = 0
        else:
            next_album_index = max_album_index + 1

        for photo_id in photo_ids:
            try:
                pending_photo = PendingPhoto.objects.get(photo_id=photo_id)
            except PendingPhoto.DoesNotExist:
                try:
                    Photo.objects.get(pk=photo_id)
                except Photo.DoesNotExist:
                    raise InvalidPhotoIdAddPhotoException()
                else:
                    pass
            else:
                try:
                    with transaction.atomic():
                        chosen_subdomain = Photo.choose_random_subdomain()
                        p = Photo.objects.create(
                            photo_id=photo_id,
                            media_type=Photo.MEDIA_TYPE_PHOTO,
                            client_upload_id="",
                            storage_id=pending_photo.storage_id,
                            subdomain=chosen_subdomain,
                            date_created=self.date_created,
                            author=pending_photo.author,
                            album=album,
                            album_index=next_album_index,
                        )
                        if chosen_subdomain in added_photos:
                            added_photos[chosen_subdomain].append(p)
                        else:
                            added_photos[chosen_subdomain] = [p]
                except IntegrityError:
                    t, v, tb = sys.exc_info()
                    # Two possible scenarios:
                    #
                    # 1)  The album_index we tried to add was already added (by a
                    #     concurrent request)
                    #
                    # 2)  photo_id was already added (by a concurrent request)

                    try:
                        Photo.objects.get(pk=photo_id)
                    except Photo.DoesNotExist:
                        # This is most likely case (1). We let the original
                        # exception bubble up (the calling code will retry this function)
                        raise t, v, tb
                    else:
                        # This is case (2)
                        # The photo is already added, so there is nothing to do
                        pass
                else:
                    # Notice that this is only incremented if a new object was
                    # actually inserted
                    next_album_index += 1

                # This is safe to call even if it was already deleted by a
                # concurrent request (will be a nop)
                pending_photo.delete()

        return added_photos