web/satellite: fix locked files number if there are folders

Right now there is a problem that we list objects inside object browser using Delimiter param which helps us to define if bucket includes folders.
If we set Delimiter to '/' then in response we get a list of plain objects called Contents and another list called CommonPrefixes which includes 'folder' keys.
So this approach makes it impossible to know the exact object count because we don't know a number of objects behind folder keys.
So to correctly calculate objects count we have to make another list request without Delimeter param.
By doing this we get a single Contents list which includes plain objects and objects containing folder Prefix.

Example of Contents response without Delimiter param:
['object', 'object1', 'folder/object2', 'folder1/object3']

Change-Id: Id23f26bed369d2063bdbae96e7d915168c6c9bdd
This commit is contained in:
Vitalii 2023-02-28 14:23:01 +02:00
parent 71e42ac2a6
commit eab83ee7fa
6 changed files with 40 additions and 27 deletions

View File

@ -5558,9 +5558,9 @@
}
},
"node_modules/caniuse-lite": {
"version": "1.0.30001390",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001390.tgz",
"integrity": "sha512-sS4CaUM+/+vqQUlCvCJ2WtDlV81aWtHhqeEVkLokVJJa3ViN4zDxAGfq9R8i1m90uGHxo99cy10Od+lvn3hf0g==",
"version": "1.0.30001458",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001458.tgz",
"integrity": "sha512-lQ1VlUUq5q9ro9X+5gOEyH7i3vm+AYVT1WDCVB69XOZ17KZRhnZ9J0Sqz7wTHQaLBJccNCHq8/Ww5LlOIZbB0w==",
"dev": true,
"funding": [
{
@ -23299,9 +23299,9 @@
}
},
"caniuse-lite": {
"version": "1.0.30001390",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001390.tgz",
"integrity": "sha512-sS4CaUM+/+vqQUlCvCJ2WtDlV81aWtHhqeEVkLokVJJa3ViN4zDxAGfq9R8i1m90uGHxo99cy10Od+lvn3hf0g==",
"version": "1.0.30001458",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001458.tgz",
"integrity": "sha512-lQ1VlUUq5q9ro9X+5gOEyH7i3vm+AYVT1WDCVB69XOZ17KZRhnZ9J0Sqz7wTHQaLBJccNCHq8/Ww5LlOIZbB0w==",
"dev": true
},
"case-sensitive-paths-webpack-plugin": {

View File

@ -275,9 +275,9 @@ const currentPath = computed((): string => {
* Return locked files number.
*/
const lockedFilesNumber = computed((): number => {
const ownObjects = store.getters['files/sortedFiles'];
const ownObjectsCount = store.state.files.objectsCount;
return objectsCount.value - ownObjects.length;
return objectsCount.value - ownObjectsCount;
});
/**

View File

@ -56,9 +56,9 @@ const NUMBER_OF_DISPLAYED_OBJECTS = 1000;
* Returns locked files number.
*/
const lockedFilesNumber = computed((): number => {
const ownObjects = store.getters['files/sortedFiles'];
const ownObjectsCount = store.state.files.objectsCount;
return objectsCount.value - ownObjects.length;
return objectsCount.value - ownObjectsCount;
});
/**

View File

@ -115,8 +115,8 @@ export default class OpenBucketModal extends Vue {
try {
this.$store.commit(OBJECTS_MUTATIONS.SET_PASSPHRASE, this.passphrase);
await this.$store.dispatch(OBJECTS_ACTIONS.SET_S3_CLIENT);
const objects = await this.$store.dispatch(OBJECTS_ACTIONS.LIST_OBJECTS, this.bucketName);
if (this.bucketObjectCount > objects.length && this.bucketObjectCount <= this.NUMBER_OF_DISPLAYED_OBJECTS) {
const count: number = await this.$store.dispatch(OBJECTS_ACTIONS.GET_OBJECTS_COUNT, this.bucketName);
if (this.bucketObjectCount > count && this.bucketObjectCount <= this.NUMBER_OF_DISPLAYED_OBJECTS) {
this.isWarningState = true;
this.isLoading = false;
return;

View File

@ -48,6 +48,7 @@ export type FilesState = {
orderBy: 'asc' | 'desc';
openModalOnFirstUpload: boolean;
objectPathForModal: string;
objectsCount: number;
};
type InitializedFilesState = FilesState & {
@ -110,6 +111,7 @@ export const makeFilesModule = (): FilesModule => ({
orderBy: 'asc',
openModalOnFirstUpload: false,
objectPathForModal: '',
objectsCount: 0,
},
getters: {
sortedFiles: (state: FilesState) => {
@ -286,6 +288,10 @@ export const makeFilesModule = (): FilesModule => ({
state.objectPathForModal = path;
},
setObjectsCount(state: FilesState, count: number) {
state.objectsCount = count;
},
addUploadToChain(state: FilesState, fn) {
state.uploadChain = state.uploadChain.then(fn);
},
@ -314,7 +320,7 @@ export const makeFilesModule = (): FilesModule => ({
},
},
actions: {
async list({ commit, state }, path = state.path) {
async list({ commit, state, dispatch }, path = state.path) {
if (listCache.has(path)) {
commit('updateFiles', {
path,
@ -324,13 +330,14 @@ export const makeFilesModule = (): FilesModule => ({
assertIsInitialized(state);
const response = await state.s3
.listObjects({
const [response] = await Promise.all([
state.s3.listObjects({
Bucket: state.bucket,
Delimiter: '/',
Prefix: path,
})
.promise();
}).promise(),
path ? undefined : dispatch('getObjectCount'),
]);
const { Contents, CommonPrefixes } = response;
@ -412,6 +419,18 @@ export const makeFilesModule = (): FilesModule => ({
dispatch('list', getParentDirectory(state.path));
},
async getObjectCount({ commit, state }) {
assertIsInitialized(state);
const responseV2 = await state.s3
.listObjectsV2({
Bucket: state.bucket,
})
.promise();
commit('setObjectsCount', responseV2.KeyCount === undefined ? 0 : responseV2.KeyCount);
},
async upload({ commit, state, dispatch }, { e, callback }: { e: DragEvent, callback: () => void }) {
assertIsInitialized(state);

View File

@ -25,7 +25,7 @@ export const OBJECTS_ACTIONS = {
CREATE_BUCKET: 'createBucket',
CREATE_BUCKET_WITH_NO_PASSPHRASE: 'createBucketWithNoPassphrase',
DELETE_BUCKET: 'deleteBucket',
LIST_OBJECTS: 'listObjects',
GET_OBJECTS_COUNT: 'getObjectsCount',
CHECK_ONGOING_UPLOADS: 'checkOngoingUploads',
};
@ -302,18 +302,12 @@ export function makeObjectsModule(): StoreModule<ObjectsState, ObjectsContext> {
Bucket: name,
}).promise();
},
listObjects: async function(ctx, name: string): Promise<S3.ObjectList> {
const response = await ctx.state.s3Client.listObjects({
getObjectsCount: async function(ctx, name: string): Promise<number> {
const response = await ctx.state.s3Client.listObjectsV2({
Bucket: name,
Delimiter: '/',
Prefix: '',
}).promise();
if (!response.Contents) {
return [];
}
return response.Contents;
return response.KeyCount === undefined ? 0 : response.KeyCount;
},
clearObjects: function({ commit }: ObjectsContext): void {
commit(CLEAR);