feat(query-optimization): implement GraphQL query optimization and enhance regression suite

- **Optimization**: Implemented automatic Zabbix parameter optimization by analyzing GraphQL selection sets.

- **ZabbixRequest**: Added optimizeZabbixParams with support for skippable parameters and implied field dependencies (e.g., state -> items).

- **Resolvers**: Updated allHosts, allDevices, allHostGroups, and templates to pass requested fields to data sources.

- **Data Sources**: Optimized ZabbixQueryHostsGenericRequest and ZabbixQueryTemplatesRequest to skip unnecessary Zabbix API calls.

- **Regression Tests**: Enhanced RegressionTestExecutor with new tests for optimization (REG-OPT, REG-OPT-NEG), state retrieval (REG-STATE), dependent items (REG-DEP), and empty results (REG-EMPTY).

- **Documentation**: Created query_optimization.md How-To guide and updated roadmap.md, README.md, and tests.md.

- **Bug Fixes**: Fixed deviceType tag assignment during host import and corrected ZabbixCreateHostRequest to support tags.
This commit is contained in:
Andreas Hilbig 2026-02-02 06:23:35 +01:00
parent ad104acde2
commit 97a0f70fd6
16 changed files with 835 additions and 69 deletions

View file

@ -62,6 +62,7 @@ import {GraphQLInterfaceType, GraphQLList} from "graphql/type/index.js";
import {isDevice} from "./resolver_helpers.js";
import {ZabbixPermissionsHelper} from "../datasources/zabbix-permissions.js";
import {Config} from "../common_utils.js";
import {GraphqlParamsToNeededZabbixOutput} from "../datasources/graphql-params-to-zabbix-output.js";
export function createResolvers(): Resolvers {
@ -102,36 +103,39 @@ export function createResolvers(): Resolvers {
allHosts: async (_parent: any, args: QueryAllHostsArgs, {
zabbixAuthToken,
cookie, dataSources
}: any) => {
}: any, info: any) => {
if (Config.HOST_TYPE_FILTER_DEFAULT) {
args.tag_hostType ??= [Config.HOST_TYPE_FILTER_DEFAULT];
}
const output = GraphqlParamsToNeededZabbixOutput.mapAllHosts(args, info);
return await new ZabbixQueryHostsRequestWithItemsAndInventory(zabbixAuthToken, cookie)
.executeRequestThrowError(
dataSources.zabbixAPI, new ParsedArgs(args)
dataSources?.zabbixAPI || zabbixAPI, new ParsedArgs(args), output
)
},
allDevices: async (_parent: any, args: QueryAllDevicesArgs, {
zabbixAuthToken,
cookie, dataSources
}: any) => {
}: any, info: any) => {
if (Config.HOST_TYPE_FILTER_DEFAULT) {
args.tag_hostType ??= [Config.HOST_TYPE_FILTER_DEFAULT];
}
const output = GraphqlParamsToNeededZabbixOutput.mapAllDevices(args, info);
return await new ZabbixQueryDevices(zabbixAuthToken, cookie)
.executeRequestThrowError(
dataSources.zabbixAPI, new ZabbixQueryDevicesArgs(args)
dataSources?.zabbixAPI || zabbixAPI, new ZabbixQueryDevicesArgs(args), output
)
},
allHostGroups: async (_parent: any, args: QueryAllHostGroupsArgs, {
zabbixAuthToken,
cookie
}: any) => {
cookie, dataSources
}: any, info: any) => {
if (!args.search_name && Config.HOST_GROUP_FILTER_DEFAULT) {
args.search_name = Config.HOST_GROUP_FILTER_DEFAULT
}
const output = GraphqlParamsToNeededZabbixOutput.mapAllHostGroups(args, info);
return await new ZabbixQueryHostgroupsRequest(zabbixAuthToken, cookie).executeRequestThrowError(
zabbixAPI, new ZabbixQueryHostgroupsParams(args)
dataSources?.zabbixAPI || zabbixAPI, new ZabbixQueryHostgroupsParams(args), output
)
},
@ -158,8 +162,8 @@ export function createResolvers(): Resolvers {
templates: async (_parent: any, args: QueryTemplatesArgs, {
zabbixAuthToken,
cookie
}: any) => {
cookie, dataSources
}: any, info: any) => {
let params: any = {}
if (args.hostids) {
params.templateids = args.hostids
@ -169,8 +173,9 @@ export function createResolvers(): Resolvers {
name: args.name_pattern
}
}
const output = GraphqlParamsToNeededZabbixOutput.mapTemplates(args, info);
return await new ZabbixQueryTemplatesRequest(zabbixAuthToken, cookie)
.executeRequestThrowError(zabbixAPI, new ParsedArgs(params));
.executeRequestThrowError(dataSources?.zabbixAPI || zabbixAPI, new ParsedArgs(params), output);
},
allTemplateGroups: async (_parent: any, args: any, {