@@ -587,15 +587,16 @@ async def generate_local_exact_thumbnail(
587
587
)
588
588
return None
589
589
590
- t_byte_source = await defer_to_thread (
591
- self .hs .get_reactor (),
592
- self ._generate_thumbnail ,
593
- thumbnailer ,
594
- t_width ,
595
- t_height ,
596
- t_method ,
597
- t_type ,
598
- )
590
+ with thumbnailer :
591
+ t_byte_source = await defer_to_thread (
592
+ self .hs .get_reactor (),
593
+ self ._generate_thumbnail ,
594
+ thumbnailer ,
595
+ t_width ,
596
+ t_height ,
597
+ t_method ,
598
+ t_type ,
599
+ )
599
600
600
601
if t_byte_source :
601
602
try :
@@ -657,15 +658,16 @@ async def generate_remote_exact_thumbnail(
657
658
)
658
659
return None
659
660
660
- t_byte_source = await defer_to_thread (
661
- self .hs .get_reactor (),
662
- self ._generate_thumbnail ,
663
- thumbnailer ,
664
- t_width ,
665
- t_height ,
666
- t_method ,
667
- t_type ,
668
- )
661
+ with thumbnailer :
662
+ t_byte_source = await defer_to_thread (
663
+ self .hs .get_reactor (),
664
+ self ._generate_thumbnail ,
665
+ thumbnailer ,
666
+ t_width ,
667
+ t_height ,
668
+ t_method ,
669
+ t_type ,
670
+ )
669
671
670
672
if t_byte_source :
671
673
try :
@@ -749,119 +751,134 @@ async def _generate_thumbnails(
749
751
)
750
752
return None
751
753
752
- m_width = thumbnailer .width
753
- m_height = thumbnailer .height
754
-
755
- if m_width * m_height >= self .max_image_pixels :
756
- logger .info (
757
- "Image too large to thumbnail %r x %r > %r" ,
758
- m_width ,
759
- m_height ,
760
- self .max_image_pixels ,
761
- )
762
- return None
763
-
764
- if thumbnailer .transpose_method is not None :
765
- m_width , m_height = await defer_to_thread (
766
- self .hs .get_reactor (), thumbnailer .transpose
767
- )
754
+ with thumbnailer :
755
+ m_width = thumbnailer .width
756
+ m_height = thumbnailer .height
768
757
769
- # We deduplicate the thumbnail sizes by ignoring the cropped versions if
770
- # they have the same dimensions of a scaled one.
771
- thumbnails : Dict [Tuple [int , int , str ], str ] = {}
772
- for requirement in requirements :
773
- if requirement .method == "crop" :
774
- thumbnails .setdefault (
775
- (requirement .width , requirement .height , requirement .media_type ),
776
- requirement .method ,
777
- )
778
- elif requirement .method == "scale" :
779
- t_width , t_height = thumbnailer .aspect (
780
- requirement .width , requirement .height
758
+ if m_width * m_height >= self .max_image_pixels :
759
+ logger .info (
760
+ "Image too large to thumbnail %r x %r > %r" ,
761
+ m_width ,
762
+ m_height ,
763
+ self .max_image_pixels ,
781
764
)
782
- t_width = min (m_width , t_width )
783
- t_height = min (m_height , t_height )
784
- thumbnails [
785
- (t_width , t_height , requirement .media_type )
786
- ] = requirement .method
787
-
788
- # Now we generate the thumbnails for each dimension, store it
789
- for (t_width , t_height , t_type ), t_method in thumbnails .items ():
790
- # Generate the thumbnail
791
- if t_method == "crop" :
792
- t_byte_source = await defer_to_thread (
793
- self .hs .get_reactor (), thumbnailer .crop , t_width , t_height , t_type
765
+ return None
766
+
767
+ if thumbnailer .transpose_method is not None :
768
+ m_width , m_height = await defer_to_thread (
769
+ self .hs .get_reactor (), thumbnailer .transpose
794
770
)
795
- elif t_method == "scale" :
796
- t_byte_source = await defer_to_thread (
797
- self .hs .get_reactor (), thumbnailer .scale , t_width , t_height , t_type
771
+
772
+ # We deduplicate the thumbnail sizes by ignoring the cropped versions if
773
+ # they have the same dimensions of a scaled one.
774
+ thumbnails : Dict [Tuple [int , int , str ], str ] = {}
775
+ for requirement in requirements :
776
+ if requirement .method == "crop" :
777
+ thumbnails .setdefault (
778
+ (requirement .width , requirement .height , requirement .media_type ),
779
+ requirement .method ,
780
+ )
781
+ elif requirement .method == "scale" :
782
+ t_width , t_height = thumbnailer .aspect (
783
+ requirement .width , requirement .height
784
+ )
785
+ t_width = min (m_width , t_width )
786
+ t_height = min (m_height , t_height )
787
+ thumbnails [
788
+ (t_width , t_height , requirement .media_type )
789
+ ] = requirement .method
790
+
791
+ # Now we generate the thumbnails for each dimension, store it
792
+ for (t_width , t_height , t_type ), t_method in thumbnails .items ():
793
+ # Generate the thumbnail
794
+ if t_method == "crop" :
795
+ t_byte_source = await defer_to_thread (
796
+ self .hs .get_reactor (),
797
+ thumbnailer .crop ,
798
+ t_width ,
799
+ t_height ,
800
+ t_type ,
801
+ )
802
+ elif t_method == "scale" :
803
+ t_byte_source = await defer_to_thread (
804
+ self .hs .get_reactor (),
805
+ thumbnailer .scale ,
806
+ t_width ,
807
+ t_height ,
808
+ t_type ,
809
+ )
810
+ else :
811
+ logger .error ("Unrecognized method: %r" , t_method )
812
+ continue
813
+
814
+ if not t_byte_source :
815
+ continue
816
+
817
+ file_info = FileInfo (
818
+ server_name = server_name ,
819
+ file_id = file_id ,
820
+ url_cache = url_cache ,
821
+ thumbnail = ThumbnailInfo (
822
+ width = t_width ,
823
+ height = t_height ,
824
+ method = t_method ,
825
+ type = t_type ,
826
+ ),
798
827
)
799
- else :
800
- logger .error ("Unrecognized method: %r" , t_method )
801
- continue
802
-
803
- if not t_byte_source :
804
- continue
805
-
806
- file_info = FileInfo (
807
- server_name = server_name ,
808
- file_id = file_id ,
809
- url_cache = url_cache ,
810
- thumbnail = ThumbnailInfo (
811
- width = t_width ,
812
- height = t_height ,
813
- method = t_method ,
814
- type = t_type ,
815
- ),
816
- )
817
828
818
- with self .media_storage .store_into_file (file_info ) as (f , fname , finish ):
819
- try :
820
- await self .media_storage .write_to_file (t_byte_source , f )
821
- await finish ()
822
- finally :
823
- t_byte_source .close ()
824
-
825
- t_len = os .path .getsize (fname )
826
-
827
- # Write to database
828
- if server_name :
829
- # Multiple remote media download requests can race (when
830
- # using multiple media repos), so this may throw a violation
831
- # constraint exception. If it does we'll delete the newly
832
- # generated thumbnail from disk (as we're in the ctx
833
- # manager).
834
- #
835
- # However: we've already called `finish()` so we may have
836
- # also written to the storage providers. This is preferable
837
- # to the alternative where we call `finish()` *after* this,
838
- # where we could end up having an entry in the DB but fail
839
- # to write the files to the storage providers.
829
+ with self .media_storage .store_into_file (file_info ) as (
830
+ f ,
831
+ fname ,
832
+ finish ,
833
+ ):
840
834
try :
841
- await self .store .store_remote_media_thumbnail (
842
- server_name ,
843
- media_id ,
844
- file_id ,
845
- t_width ,
846
- t_height ,
847
- t_type ,
848
- t_method ,
849
- t_len ,
850
- )
851
- except Exception as e :
852
- thumbnail_exists = await self .store .get_remote_media_thumbnail (
853
- server_name ,
854
- media_id ,
855
- t_width ,
856
- t_height ,
857
- t_type ,
835
+ await self .media_storage .write_to_file (t_byte_source , f )
836
+ await finish ()
837
+ finally :
838
+ t_byte_source .close ()
839
+
840
+ t_len = os .path .getsize (fname )
841
+
842
+ # Write to database
843
+ if server_name :
844
+ # Multiple remote media download requests can race (when
845
+ # using multiple media repos), so this may throw a violation
846
+ # constraint exception. If it does we'll delete the newly
847
+ # generated thumbnail from disk (as we're in the ctx
848
+ # manager).
849
+ #
850
+ # However: we've already called `finish()` so we may have
851
+ # also written to the storage providers. This is preferable
852
+ # to the alternative where we call `finish()` *after* this,
853
+ # where we could end up having an entry in the DB but fail
854
+ # to write the files to the storage providers.
855
+ try :
856
+ await self .store .store_remote_media_thumbnail (
857
+ server_name ,
858
+ media_id ,
859
+ file_id ,
860
+ t_width ,
861
+ t_height ,
862
+ t_type ,
863
+ t_method ,
864
+ t_len ,
865
+ )
866
+ except Exception as e :
867
+ thumbnail_exists = (
868
+ await self .store .get_remote_media_thumbnail (
869
+ server_name ,
870
+ media_id ,
871
+ t_width ,
872
+ t_height ,
873
+ t_type ,
874
+ )
875
+ )
876
+ if not thumbnail_exists :
877
+ raise e
878
+ else :
879
+ await self .store .store_local_thumbnail (
880
+ media_id , t_width , t_height , t_type , t_method , t_len
858
881
)
859
- if not thumbnail_exists :
860
- raise e
861
- else :
862
- await self .store .store_local_thumbnail (
863
- media_id , t_width , t_height , t_type , t_method , t_len
864
- )
865
882
866
883
return {"width" : m_width , "height" : m_height }
867
884
0 commit comments