Today, you'd typically make it async. There was a time when mainstream languages and their standard libraries didn't have async/await or things like promises and futures, so you had to do things with threads, and in some circumstances you were even doing blocking calls.
What Eric Evans (author of the original DDD book) meant by "give the illusion of an in memory collection" is, I think, more along the lines of "handle generic data retrieval and management concerns/mechanisms on behalf of domain model objects, so that the domain code wasn't littered with that stuff", rather than "pretend there's no remote database". Cause, you want your domain object to be laser-focused on capturing the business rules. It's about keeping the domain model workable and clean, easy to understand and reason about, but at the same time, you can't ignore the fact that you're making an out-of-process non-local call - you have to balance out the two.
P.S. Regarding "Collection style semantics" - that's one way to do it, but you can also organize the semantics around specific usage scenarios (what Robert Martin would call use cases). You could have multiple repos in your app, backed by the same DB, it doesn't have to be one big God object. DDD doesn't really prescribe all these (tactical) patterns people associate with it, it just gives them as an example of what you could build your system out of. DDD is about how to approach modeling, how to find out what it is that you actually need to build, and how to align your idea of the domain (your conceptual domain model) with the actual needs of the real-world domain. DDD elaborates on this, among other things, in terms of a number of high-level strategic patterns. As long as you do that, you could use a completely different set of tactical patterns, it would still be DDD.