Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/components/zod/custom-types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ export * from './json-string';
export * from './entity-name';
export * from './tenant-settings';
export * from './primitive';
export * from './string-array';
8 changes: 8 additions & 0 deletions src/components/zod/custom-types/string-array.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import {z} from 'zod';

export const stringArray = ({min = 0, max = Infinity}: {min?: number; max?: number}) => {
return z
.union([z.string(), z.array(z.string())])
.transform((val) => (typeof val === 'string' ? [val] : val))
.pipe(z.array(z.string()).min(min).max(max));
};
5 changes: 5 additions & 0 deletions src/controllers/entries/delete-entry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {AppRouteHandler} from '@gravity-ui/expresskit';

import {prepareResponseAsync} from '../../components/response-presenter';
import {makeReqParser, z, zc} from '../../components/zod';
import {EntryScope} from '../../db/models/new/entry/types';
import {LogEventType} from '../../registry/common/utils/log-event/types';
import {deleteEntry} from '../../services/entry';

Expand All @@ -11,6 +12,8 @@ const requestSchema = {
}),
query: z.object({
lockToken: z.string().optional(),
scope: z.nativeEnum(EntryScope).optional(),
types: zc.stringArray({min: 0, max: 100}).optional(),
}),
};

Expand All @@ -30,6 +33,8 @@ export const deleteEntryController: AppRouteHandler = async (req, res) => {
{
entryId: params.entryId,
lockToken: query.lockToken,
scope: query.scope,
types: query.types,
},
);

Expand Down
34 changes: 31 additions & 3 deletions src/services/entry/actions/delete-entry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,18 @@ import {AppError} from '@gravity-ui/nodekit';
import {transaction} from 'objection';

import {makeSchemaValidator} from '../../../components/validation-schema-compiler';
import {BiTrackingLogs, DEFAULT_QUERY_TIMEOUT, RETURN_COLUMNS, US_ERRORS} from '../../../const';
import {
ALLOWED_SCOPE_VALUES,
BiTrackingLogs,
DEFAULT_QUERY_TIMEOUT,
RETURN_COLUMNS,
US_ERRORS,
} from '../../../const';
import Entry from '../../../db/models/entry';
import Lock from '../../../db/models/lock';
import {EntryColumn} from '../../../db/models/new/entry';
import {WorkbookPermission} from '../../../entities/workbook';
import {DlsActions, EntryColumns, UsPermissions} from '../../../types/models';
import {DlsActions, EntryColumns, EntryScope, UsPermissions} from '../../../types/models';
import Utils, {makeUserId} from '../../../utils';
import {ServiceArgs} from '../../new/types';
import {getWorkbook} from '../../new/workbook/get-workbook';
Expand All @@ -28,20 +35,32 @@ const validateArgs = makeSchemaValidator({
useLegacyLogin: {
type: 'boolean',
},
scope: {
type: 'string',
enum: ALLOWED_SCOPE_VALUES,
},
types: {
type: 'array',
items: {
type: 'string',
},
},
},
});

export type DeleteEntryData = {
entryId: string;
lockToken?: string;
useLegacyLogin?: boolean;
scope?: EntryScope;
types?: string[];
};

export async function deleteEntry(
{ctx, skipValidation = false}: ServiceArgs,
args: DeleteEntryData,
) {
const {entryId, lockToken, useLegacyLogin = false} = args;
const {entryId, lockToken, useLegacyLogin = false, scope, types} = args;

ctx.log('DELETE_ENTRY_REQUEST', {
entryId: Utils.encodeId(entryId),
Expand All @@ -66,6 +85,15 @@ export async function deleteEntry(
entryId,
isDeleted: false,
})
.where((builder) => {
if (scope) {
builder.andWhere({[`${Entry.tableName}.${EntryColumn.Scope}`]: scope});
}

if (types) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it work good without index on entries.type
I know that we also don't have index on isDeleted but it's boolean

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It makes index scan on entryId and then filters the result, it's 1 row maximum

https://explain.tensor.ru/archive/explain/69ee14e376c7bbf98863ee3c2327e878:0:2025-09-16

builder.whereIn([`${Entry.tableName}.${EntryColumn.Type}`], types);
}
})
.first()
.timeout(DEFAULT_QUERY_TIMEOUT);

Expand Down
Loading