linqisnice
linqisnice
CC#
Created by linqisnice on 5/4/2024 in #help
Hangfire out of memory exception crashing our app services. Anyone got any advice?
No description
5 replies
CC#
Created by linqisnice on 1/25/2024 in #help
Polymorphic query handling in EF Core - Thoughts?
So I'm having to deal a lot with entity polymorphism and querying the db to avoid having to execute multiple separate queries. I'm not sure about best practices here, but i also have to eagerload certain nav props from the derived types. Anyone know a better way than this?
private async Task<IReadOnlyList<CoreProduct>> GetCoreProducts(IEnumerable<IProductRequest> requests, int internalPropertyId)
{
var query = _dbContext.Products.OfType<CoreProduct>().AsSplitQuery();

foreach(var request in requests.GroupBy(x => x.GetType(), x => x))
{
query = request switch
{
IAccommodationRequest => AccommodationQuery(query),
// more types here
_ => throw new UnreachableException()
};
}

return await query.Where(x => x.InternalPropertyId == internalPropertyId && requests.Select(x => x.ProductId).Contains(x.Id)).ToListAsync();
}

private IQueryable<CoreProduct> AccommodationQuery(IQueryable<CoreProduct> query)
=> query = query.OfType<InternalAccommodation>().Include(x => x.PriceDetails);
private async Task<IReadOnlyList<CoreProduct>> GetCoreProducts(IEnumerable<IProductRequest> requests, int internalPropertyId)
{
var query = _dbContext.Products.OfType<CoreProduct>().AsSplitQuery();

foreach(var request in requests.GroupBy(x => x.GetType(), x => x))
{
query = request switch
{
IAccommodationRequest => AccommodationQuery(query),
// more types here
_ => throw new UnreachableException()
};
}

return await query.Where(x => x.InternalPropertyId == internalPropertyId && requests.Select(x => x.ProductId).Contains(x.Id)).ToListAsync();
}

private IQueryable<CoreProduct> AccommodationQuery(IQueryable<CoreProduct> query)
=> query = query.OfType<InternalAccommodation>().Include(x => x.PriceDetails);
11 replies
CC#
Created by linqisnice on 9/3/2023 in #help
❔ Which of these two "best-fit" algorithms are better?
First one using binary search: https://paste.mod.gg/jcpadjmvfxcb/0 or the one I did before the binary search which i find way easier to read
private static List<int> FindOptimalUnits(LocalDate requestedStartDate, LocalDate requestedEndDate, int requestedQty, Dictionary<int, IPeriod[]> units)
{
var accommodationGapSize = new Dictionary<int, int>();


foreach (var unit in units)
{
var currentClosestEndDate = LocalDate.MinIsoValue;
var currentClosestStartDate = LocalDate.MaxIsoValue;

foreach (var period in unit.Value)
{
if (period.EndDate <= requestedStartDate && period.EndDate > currentClosestEndDate)
{
currentClosestEndDate = period.EndDate;
}

if (period.StartDate >= requestedEndDate && period.StartDate < currentClosestStartDate)
{
currentClosestStartDate = period.StartDate;
}

if (currentClosestEndDate == requestedStartDate && currentClosestStartDate == requestedEndDate)
{
break; // Cannot find a better
}
}

var gapSize = Period.Between(currentClosestEndDate, currentClosestStartDate, PeriodUnits.Days).Days;
accommodationGapSize.Add(unit.Key, gapSize);

}


foreach (var item in accommodationGapSize)
{
Console.WriteLine(item.Value);
}
return accommodationGapSize.OrderBy(x => x.Value).Take(requestedQty).Select(x => x.Key).ToList();
}
}
private static List<int> FindOptimalUnits(LocalDate requestedStartDate, LocalDate requestedEndDate, int requestedQty, Dictionary<int, IPeriod[]> units)
{
var accommodationGapSize = new Dictionary<int, int>();


foreach (var unit in units)
{
var currentClosestEndDate = LocalDate.MinIsoValue;
var currentClosestStartDate = LocalDate.MaxIsoValue;

foreach (var period in unit.Value)
{
if (period.EndDate <= requestedStartDate && period.EndDate > currentClosestEndDate)
{
currentClosestEndDate = period.EndDate;
}

if (period.StartDate >= requestedEndDate && period.StartDate < currentClosestStartDate)
{
currentClosestStartDate = period.StartDate;
}

if (currentClosestEndDate == requestedStartDate && currentClosestStartDate == requestedEndDate)
{
break; // Cannot find a better
}
}

var gapSize = Period.Between(currentClosestEndDate, currentClosestStartDate, PeriodUnits.Days).Days;
accommodationGapSize.Add(unit.Key, gapSize);

}


foreach (var item in accommodationGapSize)
{
Console.WriteLine(item.Value);
}
return accommodationGapSize.OrderBy(x => x.Value).Take(requestedQty).Select(x => x.Key).ToList();
}
}
4 replies
CC#
Created by linqisnice on 8/31/2023 in #help
❔ EFCore, help with atomic update along with complex conditions
Basically, I've been trying to do something like this...
var composite = await _dbContext.Inventories.Where(i => requestedQuantity.Select(x => x.AccommodationId).Contains(i.AccommodationId) && nightsInterval.Contains(i.Date))
&& requestedQuantity.All(x => x.Value <= i.TotalQuantity - i.TotalReserved).ExecuteUpdateAsync(
setters => setters.SetProperty(
i => i.TotalReserved,
i => i.TotalReserved + 1));
var composite = await _dbContext.Inventories.Where(i => requestedQuantity.Select(x => x.AccommodationId).Contains(i.AccommodationId) && nightsInterval.Contains(i.Date))
&& requestedQuantity.All(x => x.Value <= i.TotalQuantity - i.TotalReserved).ExecuteUpdateAsync(
setters => setters.SetProperty(
i => i.TotalReserved,
i => i.TotalReserved + 1));
in one atomic operation, to ensure read and write-lock on the affected items. but ot's not possible, since linq to entities cant deal with: requestedQuantity.All(x => x.Value <= i.TotalQuantity - i.TotalReserved) I've also tried a loop variation, won'tt work properly. i've been looking at transactions, but they would serialize not per accommodation but the entire method, which would lead to a massive performance bottleneck on this m ethod. I don't know any SQL so I wouldn't know where to start. Any advice?
7 replies
CC#
Created by linqisnice on 7/24/2023 in #help
❔ How would I best make this request idempotent/prevent multiple triggers
https://paste.mod.gg/nmyjoxukfxhl/0 I feel like it'd be possible (but not probable) to time out internet connection right before savechanges, whcih would make this spammable. That's obviously not great... I'm not sure which of these solutions would be better? 1: Some form of pessimistic locking(?) (so save changes BEFORE the PayoutToHost call, and then rolling back to escrow.ReleasedAt = null if !IsSuccess)
escrow.ReleasedAt = _clock.Now();
await _dbContext.SaveChangesAsync();

var payoutToHostDetails = await _paymentGateway.PayoutToHost(escrow.CancelledAmount is not null ? (decimal)escrow.CancelledAmount : escrow.FullAmount,
escrow.Id,
escrow.Currency,
host.StripeConnectAccountId!);

if (!payoutToHostDetails.IsSuccess)
{
// Roll back the pending record if the transaction fails
escrow.ReleasedAt = null;
await _dbContext.SaveChangesAsync();

return new BadRequestObjectResult(payoutToHostDetails.Error.Message);
}
escrow.ReleasedAt = _clock.Now();
await _dbContext.SaveChangesAsync();

var payoutToHostDetails = await _paymentGateway.PayoutToHost(escrow.CancelledAmount is not null ? (decimal)escrow.CancelledAmount : escrow.FullAmount,
escrow.Id,
escrow.Currency,
host.StripeConnectAccountId!);

if (!payoutToHostDetails.IsSuccess)
{
// Roll back the pending record if the transaction fails
escrow.ReleasedAt = null;
await _dbContext.SaveChangesAsync();

return new BadRequestObjectResult(payoutToHostDetails.Error.Message);
}
2. Idempotent key from client + rate limit (and then I'd have to log/check suspicious activity) 3. Something entirely different? something more robust? Or is it generally not a problem?
2 replies
CC#
Created by linqisnice on 7/18/2023 in #help
❔ Is there osme way to check if a user is active/online with aspnet core identity? (cookie)
Title is slightly incorrect: is there some way to check based on a users id if they are signed in* I understand that when you sign in, a cookie is created and sent to the browser and is then validated on each specified request. and then when you sign out, the cookie is invalidated... so there's no concept of bein "signed in"... in my situation, i need to check if x and y users are logged in inside a webhook request, and so there's no user request cycle here so i cant check the httpcontext if the request is coming from any given user. So... my thought was that I could maybe update a flag in the db when a user logs in or out, but when they close their browser, they would still be signed in but inactive. Is there soome "common" approach to this problem? how would a "last seen" function be implemented here? Would global action filter or middleware with a lastseen property be good enough?
117 replies
CC#
Created by linqisnice on 7/15/2023 in #help
❔ signalr optimistic updates excluding the connection of the user posting the message
So, I'm using signalr IHubContext to push a notification from server to client after I've confirmed that Twilio Conversations rest api has successfully persisted the message with the webhook i've set up. I do this to ensure data consistency, but it does introduce some delay. But i want an optimistic update strategy for the author of the message, so the connection from which the message is originally posted should not receive the signalr notification. I thought I should do this on the server, by wiring up some logic to get that users connectionid and excluding it in the notification... but it seems like a lot of work. is this a common problem? if so, what solutions are available? I thought of passing along a message ID to the client and then the client can ignore that signalr message for the author. Is that a viable approach?
14 replies
CC#
Created by linqisnice on 7/5/2023 in #help
❔ Is building a DM/messaging system as simple as it seems?
With signalr, that is. Is it as simple as just setting up signalr and persisting messages and then reading the messages every time the message window is opened? Or am I missing something?
66 replies
CC#
Created by linqisnice on 6/24/2023 in #help
❔ Building a location search engine (airbnb/booking style)
What is more common here? To text match locations (i.e. search USA, grab anything in the DB in the US) or to store listing locations along with coordinates, and when a search is made, convert the adderss/country/city in the search bar into coordinates and matching those iwith the ones stored in the db? Or a mix? I feel like either way, we'd need the geolocation of the geographic entity to be able to include anything within the specified radius The best approach I've come up with is this: Use bounding box (SW/NE to create a rectangle) for anything over X size (like countries and counties and states etc) and for anything smaller, like cities or towns or addresses, use a radius filter from the centroid of the geographic entity. Or is there some better way ot do it?
8 replies
CC#
Created by linqisnice on 6/16/2023 in #help
❔ accessing collections via principal entity vs directly on dbset
what is generally preferred if i want the accommodations of a listing (WITH resource ownership check included, so firstasync is intentional here)? s Doing this:
var listing = await _dbContext.Listings
.AsSplitQuery()
.Include(x => x.Accommodations).ThenInclude(x => x.Inventory)
.FirstAsync(x => x.Id == request.ListingId && x.Host.UserId == currentUserId);

var accommodations = listing.Accommodations... // just an example
var listing = await _dbContext.Listings
.AsSplitQuery()
.Include(x => x.Accommodations).ThenInclude(x => x.Inventory)
.FirstAsync(x => x.Id == request.ListingId && x.Host.UserId == currentUserId);

var accommodations = listing.Accommodations... // just an example
or actually querying accommodations directly? I find that the above seems better, since it will immediately return the request if the user does not have access. whereas if we query accommodations, it's going to reutnr an empty list and then continue I guess my question pertains in general to resource ownership and accessing a collection items via prinicipal entity vs directly on the dbset. My strategy is generally to use firstasync since if the user is not the owner of the listing, they have likely tampered with the inspector or some such to finagle the resource
8 replies
CC#
Created by linqisnice on 5/30/2023 in #help
❔ Tips on projects that will really challenge me to get better at c#/coding
So, I've built "full-fledged" enterprise airbnb type backend (production ready soon) in the last 6 months and its taught me a lot, and while its been challenging, i feel like i still struggle when it comes to more complex stuff. Like, I couldn't build anything like khellang middleware or mediatr... What are some good example projects that might push me more in that direction where im forced to learn about the intricacies of the language?
9 replies
CC#
Created by linqisnice on 5/9/2023 in #help
Price estimation of smaller AirBnb type website
Around 15-20.000 lines of code on the backend alone and 100 endpoints. Fully functioning with support for reservations, cancellations, hosting, online and offline payment, chat system, exchange rate functionality for accurate pricing etc... Would be interesting to know what such a website may cost to produce. Anyone got any ideas? I know its hard to estimate but still
13 replies
CC#
Created by linqisnice on 4/30/2023 in #help
❔ Some help configuration hellang problemdetails middleware
For those of oyu using hellang problem details middleware, did you configure it a lot? Should I make custom mapping for more specific exception types like StripeExceptions? If a CardException is thrown, I might wanna display that to the user. But currently, any exceptions not specified to be mapped by hellang default configuration are mapped to 500, which doesn't seem right for the example above. Or should I handle exceptions locally whenever I'm making external api calls or relying on external libraries? There's a lot of different approaches to exceptions, but i like the idea of a global exception handler... so I'd like to avoid handling exceptions locally. I'll do retries to minimize transient errors though. And secondly, hellang middleware is mainly for http requests right? will it even catch exceptions throw in out of process methods like hangfire background jobs etc? Do I need a custom global exception handler for that or should I just deal with it locally?
2 replies
CC#
Created by linqisnice on 4/28/2023 in #help
❔ does quartz support job queueing?
I've googled a bit but it seems it doesn't have support for queueing like hangfire or rabbitmq unless im blind or missing something. Which library preferred in this case?
2 replies
CC#
Created by linqisnice on 4/27/2023 in #help
❔ Some questions about how payment is usually handled in ecommerce
Is this a good flow (with stripe in this case) - When CreateReservation/CreatePurchase endpoint is triggered, we also create a payment intent. - We tokenize the reservation id and return it to the client - Trigger ProcessPayment endpoint, use the token to fetch the reservation and then confirm the intent that was created. In other words, two endpoints for creating purchase and finalizing payment... or even more endpoints or should it all be done without leaving the server, i.e. directly in the createreservation endpoint? That seems like a massive god class of a handler since we need to account for in person vs online payment, different payment options and methods. Bonus question: Should different payment methods and options have separate endpoints? I.e. one for klarna, one for card, one for bank etc?
2 replies
CC#
Created by linqisnice on 4/25/2023 in #help
❔ Need some help with payment processing and stripe
So... to my understanding, it's quite important to reserve/create the purchase before charging the customer since it's trivial to undo a purchase but not so to refund the customer. How is this usually done, though? Let's say I have a CreateReservation endpoint (think airbnb)... 1. Do I do all the payment processing inside this endpoint?
I don't like this because teh endpoint is already big, and there are multiple different payment options and methods so there's a lot of code and potentially "different" responses
2. Do I create a separate endpoint for PaymentProcessing and make a chain call to a separate PaymentProcessing endpoint in react after CreateReservation is successful and return the reservation Id?.
This seems unsafe, I'm not sure how to guarantee that the id isnt manipulated. Or maybe i should pass a secure token here?
3. Do I create a mediatr handler to process payment and call it from witihn the CreateReservation endpoint after creating hte reservation? There are some issues here that make it rather unintuitive for me... not the least klarna integrated with stripe, since the confirmation is actually done on teh frontend and then there is no guarantee that the user will go trhrough with the paymentintent. My solution for this is to delete all reservations and related intents if the payment status is not status "succeeded" (or with bank transfer and klarna pay later either "processing" or "requires_capture") within 10 minutes. Byt this seems like way too much work for one endpoint, but also a public facing payment endpoint with a reservationid passed in doesn't seem that great from a security perspective so the last option seems to me the safest and most logical. or none of the above and i should approach this differently Bonus question: Do i separate the endpoints/handlers for the different payment options (klarna, bank transfer, card)?
2 replies
CC#
Created by linqisnice on 4/14/2023 in #help
❔ Anyone got any advice on how to handle currencies in ecommerce/hotel booking?
I don't know if it's as straight-forward as it seems, but I'd appreciate any advice from people who've actually worked with this. By the way, I'll preface by saying that currency is not of utmost important outside of displaying prices accurately, because payment is only done in person (as of this moment). So, my initial thought was to do something like this: When a host registers a property/accommodation, he might enter the price in his local/preferred/selected currency, and then I'll store it in an implied base currency (let's say EUR) at the current conversion rate. Now, this seems pretty straight-forward. But what about conversions for displaying accurate prices? My initial thought was that this should be the frontends concern. The flow seemed more intuitive like this: Website user/guest selects preferred currency, it's stored locally, and then either a) all prices (EUR base price) are converted on the frontend to this currency (for displaying accurate prices) b) or whenever a price-related endpoint is fetched, the preferred currency is also passed in and all the prices go through a conversion engine and then are passed back to the frontend in that currency (and maybe along with the base currency too for more accuracy). Is this remotely close to what should happen? It seems relatively straight-forward if that's the case. Which option is better? Pass in selected currency + conversion on backend or simply convert visually on the frontend?
33 replies
CC#
Created by linqisnice on 4/9/2023 in #help
❔ How are prices changes/updates commonly handled in e-commerce?
Is polling/signalr used to display relevant/current prices? What about when the price changes during checkout? Do I display that to the user? Anyone got any insight or tips?
12 replies
CC#
Created by linqisnice on 3/27/2023 in #help
❔ Should photo urls be sent paginated to the frontend?
So, any given property has a collection of photos in a photo album... they are saved as urls in the db. To show this photo album, should I return all the urls in one payload and let the frontend lazy load / handle the rendering of images or should I send the paginated result to the frontend?
3 replies
CC#
Created by linqisnice on 3/25/2023 in #help
❔ How to best upload images to an entity that doesn't yet exist
Not sure if the title makes sense. When you create an accomodation, you can also upload images. But uploading images to blob storage is a different endpoint and it takes in the id of the accomodation... which doesn't yet exist. All the solutions I've come up with seem long-winded and overly complex.
12 replies