High memory usage during schema directive based field manupulation on 400k records

Hi all,
I m using schema Directive to hide/show 3-4 scalar fields based on if the user have the entitements or not. Note that the graphql result might be as big as 400k records.

As per my finding schema directive comes in the picture after all the resolvers have been fired and returned. I m not sure if schema directive actually alter in old record or duplicate it.

I m facing high memory issue… almost doubled usage with schema directive implementation (2gb → 4.5gb).

there is my code:

function hasServiceDirective(schema, directiveName) {
  return mapSchema(schema, {
	// Executes once for each object field in the schema
	[MapperKind.OBJECT_FIELD]: (fieldConfig) => {
	  // Check whether this field has the specified directive
	  const hasServiceDir = getDirective(schema, fieldConfig, directiveName)?.[0];
	  if (hasServiceDir) {
		// Get this field's original resolver
		const { resolve = defaultFieldResolver } = fieldConfig;
		let fieldName = fieldConfig.astNode.name.value;
		const serviceCode = getServiceCode(fieldName);
		// Replace the original resolver with a function that *first* calls
		// the original resolver, then converts its result based on entitlement.
		fieldConfig.resolve = async function (source, args, context, info) {
		  const result = await resolve(source, args, context, info);
		  const entitledServices = context.services;
		  if (entitledServices.includes(serviceCode)) {
			return result;
		  } else {
			return "";
		  }
		};
		return fieldConfig;
	  }
	},
  });
}

const getServiceCode = (fieldName) => {
  switch (fieldName) {
	case "CUSIP":
	  return constants.CUSIP_SERVICE_ID;
	case "ISIN":
	  return constants.ISIN_SERVICE_ID;
	case "LocalCode":
	case "Ticker":
	  return constants.LOCALCODE_SERVICE_ID;
	case "SEDOL":
	  return constants.SEDOL_SERVICE_ID;
	default:
	  return constants.QUODD_QDOD_SERVICE_ID;
  }
};

As per my finding schema directive comes in the picture after all the resolvers have been fired and returned. I m not sure if schema directive actually alter in old record or duplicate it.

You’re explicitly calling resolve() in your directive resolver, so you should expect the other resolvers to be executed first.

I would recommend making sure you place your @service() resolver first on these fields, because if I recall correctly, directives are resolved in the order they appear in the schema.


I would check if your memory usage is cleaned up afterwards via the chrome node profiler, and I would also try this:

fieldConfig.resolve = async function (source, args, context, info) {
  const entitledServices = context.services;
  if (entitledServices.includes(serviceCode)) {
	return await resolve(source, args, context, info);
  } else {
	return null;
  }
};