-
-
Notifications
You must be signed in to change notification settings - Fork 2.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Upgrade all dependencies #11612
Upgrade all dependencies #11612
Conversation
Several issues, even if it passes CI (which it won't, due to a code style failure - there's a leftover using statement in
You've even attached those in discord and them promptly ignored them. That can't land in a release. We'll get swamped with issue reports.
If it were just an issue of bumping the versions we'd have done so by now. Are you going to be trying to fix these issues at all? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
as above
I'm trying to fix them in next several days. |
For the SignalR side, I was looking at bumping/testing it yesterday and was blocked by the dependency chain. I'll take a look at that part on this branch, as it is likely resolved (see #osu-lazer backlog for the troubles I had with dependency resolution). The database import failures are probably the same thing I was seeing last time I attempted to upgrade to the newer ef-core. I believe the cause is that we are doing threading wrong. Again, if there's a simple fix for this then we can definitely go with it, but if it's a larger conceptual change/refactor it may still be worth waiting on the realm path forward. |
Have tested against iOS and things look... as good as they can be. Ran into an issue with SignalR AOT, but that is going to be an issue regardless (hoping for a reply at MessagePack-CSharp/MessagePack-CSharp#780 (comment)). I will take a look into the import issues next. |
@hez2010 are you already looking into the tracking entity issues? if so i'll stop doing so until you've come to a conclusion and focus elsewhere. |
Found some clues: I think a possible solution is to split FileInfo addition and beatmap addition into two stages: adding FileInfos (or querying FileInfoID) first and calling SaveChanges, and then processing beatmap with quried |
@hez2010 i also looked into the same path, but i also:
At this point, the If you are able to make it work with your strategy of a double pass, then that should be sufficient for now, given that we are hopefully moving away from EF in the future so this is all temporary. I'll leave it in your hands for now; let me know if you give up and I will try again. |
|
I used
|
...this has 300 files changed now and a diffstat in thousands of lines. the PR is now borderline unreviewable with code changes intermingled with formatting changes and dependency bumps. that is not how things should ever be done. |
This reverts commit 7a9ec4c.
I've reverted most of the changes. Please only commit further database fixes to this branch or we will be forces to start a separate branch from scratch. |
@peppy All tracking issues of migrations and imports have been resolved via splitting one transaction into multiple transactions. Now the last issue remaining: In test code (such as osu.Game.Tests/TestSceneMatchSongSelect): new BeatmapInfo
{
// ...
Ruleset = new OsuRuleset().RulesetInfo // boom
}, |
[JsonIgnore] | ||
[Column("Mods")] | ||
public string ModsJson |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what was wrong with this property?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since Mods
is not mapped and ModsJson
is mapped as Mods
column, only changes to ModsJson
can make efcore 5 detect changes in Mods
. So here we should apply changes to ModJson
to make sure changes are being tracked by efcore, and use Mods
for json deserialization. Otherwise some tests will also fail.
not sure how to review this change without going myself and reverse-engineering it all, without any actual reasoning provided for any of these changes. |
@bdach Most changes you previously reviewed have been reverted. My solution is always looking up latest entries and replacing the old same |
for (int i = beatmapSet.Files.Count - 1; i >= 0; i--) | ||
{ | ||
var file = beatmapSet.Files[i]; | ||
var id = file?.FileInfo?.ID; | ||
|
||
if (id != null && id != 0) | ||
{ | ||
if (latestFileInfos.ContainsKey(id.Value)) | ||
{ | ||
file.FileInfo = latestFileInfos[id.Value]; | ||
} | ||
else | ||
{ | ||
latestFileInfos[id.Value] = file.FileInfo; | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
how does this work? this silently assumes that the last beatmap set was fetched from EF last, and therefore has the freshest entity?
not sure i like this at all. it's very precarious. would probably rather just do a full refetch of everything, definitely feels much safer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
New modified FileInfo
s will be appended to Files
, and with changes of Reference
and Dereference
, old entries in the list will be updated by ref
, so here we only need to keep the last modified one.
|
||
public void Reference(ref FileInfo file) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not sure on doing the refetch as part of the {Reference,Dereference}
operations. looks super awkward and clunky (especially in usage code). would just do that explicitly via Find
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It won't going to work. Any modification to the one which loaded from database via Find
doesn't affect the originally exist one, after calling Update
in FileStore
the modified one will be tracked, so the later call to Add
in ArchiveModelManager
will lead to multiple FileInfo
with same ID but different ReferenceCount
coexist in ChangeTracker and cause tracking conflicts.
The cheapest solution is to use the modified one to replace the original one after Update
, here I use ref
to achieve this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also had a similar implementation to this in my attempt to fix this. I don't think it's too bad.
write.Context.ChangeTracker.Entries() | ||
.Where(e => e.State == EntityState.Unchanged) | ||
.ToList() | ||
.ForEach(e => e.State = EntityState.Detached); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this "detach everything and try saving" actually seems like a more promising way to do all of this. if we use that approach everywhere, will it work?
just feels like a simpler way to deal.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unfortunately it only solves the problem when entities already in ChangeTracker before calling Add
, but entities with same id in item
will still cause tracking conflict issues.
@@ -366,8 +411,7 @@ public IEnumerable<BeatmapSetInfo> GetAllUsableBeatmapSetsEnumerable(IncludedDet | |||
|
|||
// AsEnumerable used here to avoid applying the WHERE in sql. When done so, ef core 2.x uses an incorrect ORDER BY | |||
// clause which causes queries to take 5-10x longer. | |||
// TODO: remove if upgrading to EF core 3.x. | |||
return queryable.AsEnumerable().Where(s => !s.DeletePending && (includeProtected || !s.Protected)); | |||
return queryable.Where(s => !s.DeletePending && (includeProtected || !s.Protected)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The remaining comment above can also be removed if this is deemed resolved.
|
||
public void Reference(ref FileInfo file) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also had a similar implementation to this in my attempt to fix this. I don't think it's too bad.
@@ -88,6 +89,42 @@ protected override bool CheckLocalAvailability(ScoreInfo model, IQueryable<Score | |||
=> base.CheckLocalAvailability(model, items) | |||
|| (model.OnlineScoreID != null && items.Any(i => i.OnlineScoreID == model.OnlineScoreID)); | |||
|
|||
protected override void PreImport(ScoreInfo model) | |||
{ | |||
var latestFileInfos = new Dictionary<int, FileInfo>(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what is this whole block doing?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some tracking issues were caused by FileInfo
in .Files
with same ID
but different ReferenceCount
, so it enumerates the list by desc and use latest entries to replace old entries (since the newly modified one must be ranked behind the previous one in List<T>
). Although I don't know why there're FileInfo
entries with same ID in the list.
Same for RulesetInfo
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd personally be more fine with this sort of trick if we could ask EF for the newest entry, instead of essentially guessing at random that the entities at the end of the list are the newest entry.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The modifications haven't been committed into database yet so there won't be latest entries from EF.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
very confused as to what committing to DB has to do with EF entry tracking. this is a DbContext
level issue, correct? can't DbContext.ChangeTracker.Entries()
be used or something?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Both modified and unmodified entries are in item
which are causing tracking conflicts while adding it to ChangeTracker, and before calling Add(item)
there're no entries in ChangeTracker.
@peppy A more elegant way without these tricks is to use lazy loading mode in EF, which can avoid most all above problems. But this would require large code changes. |
I do believe this PR is going to be stuck in a permanent stalemate with the current state of changes. While what you've added here may work correctly, there's just too many individual hacks to instill any degree of confidence. There's a high chance that something else is going to break as a result of these changes and either go unnoticed or cause new bugs to arise. |
|
@peppy What do you think? |
That sounds fine, but only if you are okay with the work you do potentially not being used (we can't guarantee it will be merged, depending on complexity). We are still intent on switching to Realm but waiting on an upstream threading crash that needs to be resolved before we can deploy it. |
@hez2010 thanks for your work on this. I'm going to close this in favour of #12003, which reduces the number of workarounds required to get this working. Probably wouldn't have happened without this PR pushing things in this direction, so hopefully it doesn't feel like this being closed makes it in vain. |
An attempt of upgrading all dependencies to latest, to see whether things are going to work or not.