2222
2323/**
2424 * @psalm-import-type ObjectStoreConfig from PrimaryObjectStoreConfig
25- * @psalm-type ObjectStoreDefinition = array{store: IObjectStore, objectPrefix : string, config?: ObjectStoreConfig }
25+ * @psalm-type ObjectStoreDefinition = array{store: IObjectStore, urn : string}
2626 */
2727class ObjectStorePreviewStorage implements IPreviewStorage {
2828
2929 /**
30- * @var array<string, array<string, ObjectStoreDefinition >>
30+ * @var array<string, array<string, IObjectStore >>
3131 */
3232 private array $ objectStoreCache = [];
3333
@@ -49,13 +49,12 @@ public function writePreview(Preview $preview, mixed $stream): int {
4949 });
5050
5151 [
52- 'objectPrefix ' => $ objectPrefix ,
52+ 'urn ' => $ urn ,
5353 'store ' => $ store ,
54- 'config ' => $ config ,
55- ] = $ this ->getObjectStoreForPreview ($ preview );
54+ ] = $ this ->getObjectStoreInfoForNewPreview ($ preview );
5655
5756 try {
58- $ store ->writeObject ($ this -> constructUrn ( $ objectPrefix , $ preview -> getId ()) , $ countStream );
57+ $ store ->writeObject ($ urn , $ countStream );
5958 } catch (\Exception $ exception ) {
6059 throw new NotPermittedException ('Unable to save preview to object store ' , previous: $ exception );
6160 }
@@ -65,24 +64,26 @@ public function writePreview(Preview $preview, mixed $stream): int {
6564 #[Override]
6665 public function readPreview (Preview $ preview ): mixed {
6766 [
68- 'objectPrefix ' => $ objectPrefix ,
67+ 'urn ' => $ urn ,
6968 'store ' => $ store ,
70- ] = $ this ->getObjectStoreForPreview ($ preview );
69+ ] = $ this ->getObjectStoreInfoForExistingPreview ($ preview );
70+
7171 try {
72- return $ store ->readObject ($ this -> constructUrn ( $ objectPrefix , $ preview -> getId ()) );
72+ return $ store ->readObject ($ urn );
7373 } catch (\Exception $ exception ) {
74- throw new NotPermittedException ('Unable to read preview from object store ' , previous: $ exception );
74+ throw new NotPermittedException ('Unable to read preview from object store with urn: ' . $ urn , previous: $ exception );
7575 }
7676 }
7777
7878 #[Override]
7979 public function deletePreview (Preview $ preview ): void {
8080 [
81- 'objectPrefix ' => $ objectPrefix ,
81+ 'urn ' => $ urn ,
8282 'store ' => $ store ,
83- ] = $ this ->getObjectStoreForPreview ($ preview );
83+ ] = $ this ->getObjectStoreInfoForExistingPreview ($ preview );
84+
8485 try {
85- $ store ->deleteObject ($ this -> constructUrn ( $ objectPrefix , $ preview -> getId ()) );
86+ $ store ->deleteObject ($ urn );
8687 } catch (\Exception $ exception ) {
8788 throw new NotPermittedException ('Unable to delete preview from object store ' , previous: $ exception );
8889 }
@@ -91,72 +92,83 @@ public function deletePreview(Preview $preview): void {
9192 #[Override]
9293 public function migratePreview (Preview $ preview , SimpleFile $ file ): void {
9394 // Just set the Preview::bucket and Preview::objectStore
94- $ this ->getObjectStoreForPreview ($ preview , true );
95+ $ this ->getObjectStoreInfoForNewPreview ($ preview , migration: true );
9596 $ this ->previewMapper ->update ($ preview );
9697 }
9798
9899 /**
99100 * @return ObjectStoreDefinition
100101 */
101- private function getObjectStoreForPreview (Preview $ preview , bool $ oldFallback = false ): array {
102- if ($ preview ->getObjectStoreName () === null ) {
103- $ config = $ this ->objectStoreConfig ->getObjectStoreConfiguration ($ oldFallback ? 'root ' : 'preview ' );
104- $ objectStoreName = $ this ->objectStoreConfig ->resolveAlias ($ oldFallback ? 'root ' : 'preview ' );
105-
106- $ bucketName = $ config ['arguments ' ]['bucket ' ];
107- if ($ config ['arguments ' ]['multibucket ' ]) {
108- if ($ this ->isMultibucketPreviewDistributionEnabled ) {
109- $ oldLocationArray = str_split (substr (md5 ((string )$ preview ->getFileId ()), 0 , 2 ));
110- $ bucketNumber = hexdec ('0x ' . $ oldLocationArray [0 ]) * 16 + hexdec ('0x ' . $ oldLocationArray [0 ]);
111- $ bucketName .= '-preview- ' . $ bucketNumber ;
112- } else {
113- $ bucketName .= '0 ' ;
114- }
115- }
116- $ config ['arguments ' ]['bucket ' ] = $ bucketName ;
102+ private function getObjectStoreInfoForExistingPreview (Preview $ preview ): array {
103+ assert (!empty ($ preview ->getObjectStoreName ()));
104+ assert (!empty ($ preview ->getBucketName ()));
105+
106+ $ config = $ this ->objectStoreConfig ->getObjectStoreConfiguration ($ preview ->getObjectStoreName ());
107+ $ config ['arguments ' ]['bucket ' ] = $ preview ->getBucketName ();
108+ $ objectStoreName = $ preview ->getObjectStoreName ();
109+
110+ return [
111+ 'urn ' => $ this ->getUrn ($ preview , $ config ),
112+ 'store ' => $ this ->getObjectStore ($ objectStoreName , $ config ),
113+ ];
114+ }
117115
118- $ locationId = $ this ->previewMapper ->getLocationId ($ bucketName , $ objectStoreName );
119- $ preview ->setLocationId ($ locationId );
120- $ preview ->setObjectStoreName ($ objectStoreName );
121- $ preview ->setBucketName ($ bucketName );
122- } else {
123- $ config = $ this ->objectStoreConfig ->getObjectStoreConfiguration ($ preview ->getObjectStoreName ());
124- $ config ['arguments ' ]['bucket ' ] = $ bucketName = $ preview ->getBucketName ();
125- $ objectStoreName = $ preview ->getObjectStoreName ();
116+ /**
117+ * @return ObjectStoreDefinition
118+ */
119+ private function getObjectStoreInfoForNewPreview (Preview $ preview , bool $ migration = false ): array {
120+ // When migrating old previews, use the 'root' object store configuration
121+ $ config = $ this ->objectStoreConfig ->getObjectStoreConfiguration ($ migration ? 'root ' : 'preview ' );
122+ $ objectStoreName = $ this ->objectStoreConfig ->resolveAlias ($ migration ? 'root ' : 'preview ' );
123+
124+ $ bucketName = $ config ['arguments ' ]['bucket ' ];
125+ if ($ config ['arguments ' ]['multibucket ' ]) {
126+ if ($ this ->isMultibucketPreviewDistributionEnabled ) {
127+ // Spread the previews on different buckets depending on their corresponding fileId
128+ $ oldLocationArray = str_split (substr (md5 ((string )$ preview ->getFileId ()), 0 , 2 ));
129+ $ bucketNumber = hexdec ('0x ' . $ oldLocationArray [0 ]) * 16 + hexdec ('0x ' . $ oldLocationArray [0 ]);
130+ $ bucketName .= '-preview- ' . $ bucketNumber ;
131+ } else {
132+ // Put all previews in the root (0) bucket
133+ $ bucketName .= '0 ' ;
134+ }
126135 }
136+ $ config ['arguments ' ]['bucket ' ] = $ bucketName ;
137+
138+ // Get the locationId corresponding to the bucketName and objectStoreName, this will create
139+ // a new one, if no matching location is found in the DB.
140+ $ locationId = $ this ->previewMapper ->getLocationId ($ bucketName , $ objectStoreName );
141+ $ preview ->setLocationId ($ locationId );
142+ $ preview ->setObjectStoreName ($ objectStoreName );
143+ $ preview ->setBucketName ($ bucketName );
144+
145+ return [
146+ 'urn ' => $ this ->getUrn ($ preview , $ config ),
147+ 'store ' => $ this ->getObjectStore ($ objectStoreName , $ config ),
148+ ];
149+ }
127150
128- $ objectPrefix = $ this ->getObjectPrefix ($ preview , $ config );
151+ private function getObjectStore (string $ objectStoreName , array $ config ): IObjectStore {
152+ $ bucketName = $ config ['arguments ' ]['bucket ' ];
129153
130154 if (!isset ($ this ->objectStoreCache [$ objectStoreName ])) {
131155 $ this ->objectStoreCache [$ objectStoreName ] = [];
132- $ this ->objectStoreCache [$ objectStoreName ][$ bucketName ] = [
133- 'store ' => $ this ->objectStoreConfig ->buildObjectStore ($ config ),
134- 'objectPrefix ' => $ objectPrefix ,
135- 'config ' => $ config ,
136- ];
156+ $ this ->objectStoreCache [$ objectStoreName ][$ bucketName ] = $ this ->objectStoreConfig ->buildObjectStore ($ config );
137157 } elseif (!isset ($ this ->objectStoreCache [$ objectStoreName ][$ bucketName ])) {
138- $ this ->objectStoreCache [$ objectStoreName ][$ bucketName ] = [
139- 'store ' => $ this ->objectStoreConfig ->buildObjectStore ($ config ),
140- 'objectPrefix ' => $ objectPrefix ,
141- 'config ' => $ config ,
142- ];
158+ $ this ->objectStoreCache [$ objectStoreName ][$ bucketName ] = $ this ->objectStoreConfig ->buildObjectStore ($ config );
143159 }
144160
145161 return $ this ->objectStoreCache [$ objectStoreName ][$ bucketName ];
146162 }
147163
148- private function constructUrn (string $ objectPrefix , int $ id ): string {
149- return $ objectPrefix . $ id ;
150- }
151-
152- public function getObjectPrefix (Preview $ preview , array $ config ): string {
164+ public function getUrn (Preview $ preview , array $ config ): string {
153165 if ($ preview ->getOldFileId ()) {
154- return $ config ['arguments ' ]['objectPrefix ' ] ?? 'uri :oid: ' ;
166+ return ( $ config ['arguments ' ]['objectPrefix ' ] ?? 'urn :oid: ' ) . $ preview -> getOldFileId () ;
155167 }
156168 if (isset ($ config ['arguments ' ]['objectPrefix ' ])) {
157- return $ config ['arguments ' ]['objectPrefix ' ] . 'preview: ' ;
169+ return ( $ config ['arguments ' ]['objectPrefix ' ] . 'preview: ' ) . $ preview -> getId () ;
158170 } else {
159- return 'uri:oid:preview: ' ;
171+ return 'uri:oid:preview: ' . $ preview -> getId () ;
160172 }
161173 }
162174
0 commit comments