Closed szamanr closed 1 month ago
Having a similar issue with our usage. Would be interesting to know if there is a bug or not.
Going to look into it myself soon.
That's possible we have a bug. I don't have time right now to check it, but PRs are welcome!
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
it is still occurring which is preventing me from using this library. i am currently implementing my mock functions manually but it's a laborious workaround.
please don't close.
I wonder if this is because the default override is an object - whereas you override to an array?
// more fields here, but not relevant: if i comment out all relationships, test completes. if i have at least 1 relationship uncommented, if freezes.
@szamanr
Would you mind expanding on this comment a bit more? Does this happen if any relationship is present? Or it only happens when the commits
relationship is uncommented?
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
This is still broken based on what I've seen so far. terminateCircularRelationships is not working for us.
I tested the code above and didn't reach an oom. However:
We have a big schema which is pretty much what a graph looks like. Many circular references. We're reaching an oom and by logging the creation of mocks I see the same objects being created multiple times. This is expected but can be a big problem. Depending on the number of branches this can grow quite big before a mock finds all the rules to stop creating submocks.
To have working mocks I just didn't create a new set each time a mock is created and let it reuse the same one every time.
export const aMock = (overrides?: Partial<Mock>, relationshipsToOmit: Set<string> = new Set()): { __typename: 'Mock' } & Mock => {
relationshipsToOmit.add('Mock');
console.log('relationshipsToOmit', relationshipsToOmit);
This made the mock generation finish without the oom.
Although this works for us I understand that beginning with a new set each time is what makes sense because you want to create a full mock with the exception of the type that created the mock in the first place. However.... OOM.
I don't know if there's a clean solution here.
The workaround we found was to have another plugin create a set of Relationships per type ahead of time to feed it to the mock creation.
As I suggestion, I would make the the relationship logic the opposite. If a Set
with relationships is passed, the mocks for those relationships would be created and only at that level.
If this suggestion is acceptable, I'd be open to creating a PR
Interesting, we definitely have a performance/memory issue if we create a new set everytime. I'm however not sure to understand your suggestion, we're opened to PR though.
@rpereira-anchor Could you elaborate a bit more on your suggestion before getting too deep in the implementation?
Thanks !
Interesting, we definitely have a performance/memory issue if we create a new set everytime. I'm however not sure to understand your suggestion, we're opened to PR though.
@rpereira-anchor Could you elaborate a bit more on your suggestion before getting too deep in the implementation?
Thanks !
@ardeois The suggestion would be a breaking change.
I understand... I don't really like this breaking change
Maybe a better fix would be to not create a new set with default values everytime new Set(_relationshipsToOmit);
but instead reuse the Set
.
Is that what you were suggesting about reusing the Set
?
// BEFORE
export const aCycleCheckins = (overrides?: Partial<CycleCheckins>, _relationshipsToOmit: Set<string> = new Set()): { __typename: 'CycleCheckins' } & CycleCheckins => {
const relationshipsToOmit: Set<string> = new Set(_relationshipsToOmit);
relationshipsToOmit.add('CycleCheckins');
return {
__typename: 'CycleCheckins',
checkIns: overrides && overrides.hasOwnProperty('checkIns') ? overrides.checkIns! : [relationshipsToOmit.has('CheckIn') ? {} as CheckIn : aCheckIn({}, relationshipsToOmit)],
start: overrides && overrides.hasOwnProperty('start') ? overrides.start! : 'laboriosam',
// more non-relationship fields here
};
}
// AFTER
export const aCycleCheckins = (
overrides?: Partial<CycleCheckins>,
_relationshipsToOmit?: Set<string>,
): { __typename: 'CycleCheckins' } & CycleCheckins => {
const relationshipsToOmit: Set<string> = _relationshipsToOmit || new Set();
relationshipsToOmit.add('CycleCheckins');
return {
__typename: 'CycleCheckins',
checkIns:
overrides && overrides.hasOwnProperty('checkIns')
? overrides.checkIns!
: [relationshipsToOmit.has('CheckIn') ? ({} as CheckIn) : aCheckIn({}, relationshipsToOmit)],
start: overrides && overrides.hasOwnProperty('start') ? overrides.start! : 'laboriosam',
// more non-relationship fields here
};
};
Would you be able to test if that fixes your infinite loop?
@ardeois That was the test I made initially. It does fix the problem.
Ok so let's go with this approach then. I think a unit test will fail about this, somebody made a PR a long time ago to create a new Set everytime but I don't remember the use case Unit tests will tell us why 🙂
Thanks for tracking this out
We could maybe introduce a new option to use an optimized version of terminateCircularRelationships
, using your suggestion, or keep the non-optimized version to avoid breaking changes
@ardeois Maybe reusing the existing option could do it. I think that making terminateCircularRelationships
receive true
, false
or immediate
could work.
immediate
would not recreate the set on every new mock. It would not be a breaking change as the existing usage would be safe.
immediate
was my first thought but anything that better conveys the intention is fine by me.
WDYT?
Yes very good idea !
Cool! I think I'll be able to make a PR this week.
@ardeois let me know of any changes you need in the PR. Thank you.
hi! i'm using
"graphql-codegen-typescript-mock-data": "3.3.1",
with settingterminateCircularRelationships: true
. when i run a test using the mocks, it runs for a while and eventually runs out of memory:FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory
.if i override the relationship as an empty array, the test completes as expected.
this is my codegen config:
(index.ts is generated by codegen as well)
❌ this breaks:
✅ this works:
my schema looks like this:
the loop in the generated code looks like this: aCycleCheckins: checkIns → aCheckIn: commits → aCommitConnection → aCommitEdge → aCommit: checkIn → aCheckIn
this is the generated code:
this is the first test where i tried using this plugin, so i don't know if it works for other models.
is it an issue in my schema that i happened to run into in the first test? or is there something wrong with the plugin and the
terminateCircularRelationships
option isn't working?