Frank (00:08): Hi James, I want to talk about, Frank (00:11): they didn't open source projects because I finally, finally, finally updated SQL Lite bash net and I felt a little bit terrible because it was a little bit long between releases and there were some nasty bugs out there and I learned a lot of important lessons along the way. How does that sound for a topic? James (00:31): That sounds good. I also have a lot of open source projects that I need to update and then never update because other things come up in life and we're in a global pandemic. So I hear you. I mean, I'm there for you. And in fact while we do this podcast, I'm gonna to update one of my libraries with the update that you just came out with to this library. Frank (00:50): I'm scared already. How exciting. So, um, just to say everyone out there, if you're using a library right called SQL light dash net, I released version 1.7 just to, Oh, I don't know. And in podcast time I have no idea, but about a week ago. And, um, I'm very excited because it honestly has some pretty big bug fixes that I guess I alluded to should have been fixed a lot sooner and people are getting kind of mad and the issues. So I'm trying to, it's trying to temper the storm a little bit and apologize and make good on, um, making sure the library is interesting and so you updating to it is filling me with even more worry but we can get there. James (01:33): Yeah, I'm sure it'll be just fine. Frank. I mean you just alluded that you had no issues at all and then everything was gravy. Frank (01:39): Right? We are going to talk about unit tests and how much I trust unit test and how much I distrust unit tests during all of this. Um, but first I want to talk about um, this unfortunate regression that came up mostly because the library is being used in a way that I guess I didn't originally intend, but I was always like, yeah, yeah, totally works in this environment. But it was a little bit new to me. It turns out, James, I wrote this library to work on mobile devices, but people keep using it on websites. Why do you remember, um, I think maybe about a million episodes ago, we talked about using SQL Lite as your database for a website. There's pros and cons. The pros mostly being it's super developer friendly, easier to work with. The cons being like E I don't know if I should run SQL Lite on a website kind of thing. James (02:36): I remember you telling me that we were talking about databases and back ends. I mean this was a while ago, but I remember you telling me that SQL Lite does great on the internet and Frank (02:46): that don't you run a website based off of with SQL and backend? I don't use it as a hundred percent of a website anywhere, but I use it as parts of a website. Um, if I'm fully honest, parts of the website that I don't think would destroy the world if they broke. So I'm just, you know, I haven't had like the full guts to use it for say, user registration, um, things like that. But, um, if you do file new, not file new project.net new web app with identity something or another, you get an asp.net core website that uses entity framework to use SQL Lite. That's the default. James (03:28): Oh yeah, yes, yes, yes. Cause, um, there's, I was setting up and doing an entity framework tutorial recently and I want to, to kind of walk through it and the default is, um, in memory, which makes a lot of sense because I'm just doing it in memory cache. But then the next thing was sequel light and then the next thing was SQL database kind of like progressing, like hook it up to a real database. And the advantage there is in memory, you know, if you do an in memory cache, it's not going to store anything when you turn it off. But if you're doing SQL Lite, then bingo. Bango right. You've got a great Frank (04:07): website ready to go. Yeah. You have a very basic database engine that is pretty battle-tested. Uh, definitely not going to have the same performance characteristics as sequel light. But at CQL, sorry, or my SQL or postcard or any of those things. Um, but okay, so, okay, so number one, they're using our library in an environment that I'm not, I never quite intended, but I keep saying it's going to work in, James (04:32): it was not Frank approved it. It didn't have a stamp of approval from this is how you may think about using this library. Frank (04:40): More of like I, I know my libraries are good when I use them in my own apps because then I have like customer feedback. I'm fixing bugs. That's when I can say a hundred percent confidence. This library works. Yeah, it's got bugs, everything. It's got bugs, but you know the major parts of it work. I didn't have any websites that were running, you know, a hundred percent SQL Lite dash net. James (05:02): One thing too is I will say on that statement, I believe my best libraries the most, you know, book free in quotes and feature rich libraries are the ones that I'm actively using inside of active applications. And you know the ones that I'm not using because they are much less actively, do you know what I mean? Like for monkey cash, I use the file system cache because John Dick wrote and it's basically flawless and I, and it's like it's done and I'm like I don't know what else to do. It's just done like it met my criteria and I don't yet, I don't use the like, you know, offense, I don't use the SQL I on cause I'm not using sequel light in my apps and I'm not using the file DB one cause I'm not, you know, doing that. So I, I ended up testing them less as far as the dependencies. James (05:52): Right. There's other things that are happening. There's different use cases. It's just clear, Hey there's this or the other thing I will say too is when somebody else adds a feature to your library that you didn't want, but they're like, this would be a great feature, then you automatically kind of not, don't test that one as much because you know why you didn't develop the feature and you're probably not going to use it. Reality as reality. It's just facts. I'm not trying to be me. It's I love, I love people contributing. I love, I love all of you. I'm just saying that that's one downside to that. Frank (06:28): Well we all do test driven development so that it wouldn't exist unless we needed it. Right. That API. Yeah, exactly. Well, okay, so there's this funny world that they're running my library and then I'm like okay that should work. But then my API is also split James. It's a split personality library. It has a synchronous version or let's call that iOS 2.0 days. That's what I use. Yeah. Yeah. Everyone loves the synchronous version under sound, everything. And just make sure it's all good to go. Yeah. Locks. That's always good to put in our code. And guess what? That's going to be the main theme of this podcast today. Always be locking. I said, see I was going to try to like circle around the topic a little bit more, but you just, you saw it coming and you just put your eyes. James (07:17): Okay. So, cause you said, you know, iOS two days and I've been, well one, I've been using SQL Lite for SQL eight dash and net by the way, for how long now? Nine years. And you know what I mean? We met if people can go back, we met because I knew Kruger systems inc from your stupid source code file that I would download and put into all every single one of my apps and put into my, you know, about page and thanking for amazing software that works. Do I know how it worked? I have no idea. I remember when it could just be a source code and you have to worry about like Siebel bond security things. But anyways, um, but yeah, no, I mean it's something that I've used for a long time is how we met was literally how we became friends and because of SQL light dash net, that's how this podcast exists. Frank (08:06): Yeah. You're making me nervous. So like if I break this library too much, does that break the friendship transitive profits? Correct. That's a true statement. Okay. This library means a lot to me now. Um, so yeah, so because it's forever old, it went through a sweat personality phase where it all signed, gained in a sink portion to it. And this was in a very early days of async, like in the, um, very early Xamarin days. We couldn't even use a, um, a wait, it didn't exist like it was there. The compiler could do it, but the runtime couldn't handle it. So like we were doing tasks.run dot. Continue with, you know, that kind of stuff. That's the good stuff. And the, yeah, in the very early days. And it was in those very early days when we were learning how async works that I wrote all that code and Oh boy, Oh boy, James, I made some mistakes and some of those mistakes are finally coming back to bite me. That was, that was the politest way I can put it. Sorry. James (09:11): No, I mean, I think that that, uh, that, that, uh, makes some sense. I mean, I think it was a transition period for all of us in life and there comes a point in every library's life where, you know, it's starting to grow up a little bit and, and um, it's sort of an awkward phase in life. I've been there personally, I'm still in my awkward phase, so there's that, you know. Um, and uh, yeah I can understand where this is going. And in fact I will say, I remember, I remember the move to async because I believe it was windows store application. Windows store eight was the first one where everything became a synchronous. And then even the first time in which I think maybe I was using African, how I was doing it. I think I had like just uh, Oh I had, you know what I did, I had a linked file, remember linked files? Oh yeah, they were before share projects. And then I would conditionally compile the code in my re, you know, data repository service to either use the async version of the non hazing version. It was like big mashup. And then the aid, this aid, the sink one had like locks around everything. It was, it was a fascinating, Frank (10:21): yeah. Okay. Um, right. So these, those were exactly the heady days. Fascinating. Was that a wonderful adjective for you to choose there? Thanks. Yes. So, um, for this next part I have to get a tiny bit technical. You mind w we gotta talk about locks. Go for it. Locked in and up. So the truth is no, SQL Lite database is really that multithreaded friendly. It's just not, you can try, but you're going to get like problems. It gets locked, it gets busy. It has all its own internal stuff. So the way that async version of SQL light dash networked was, it had just a shared connection and any time you wanted to use that connection, it itself would put a lock on it and run it in the thread pool. Simple as that. So put a lock on it so that only one piece of code can actually use the database in a row and throw it in a thread pool so that it can get, be queued to run later. James (11:21): That sounds fine. Right? That sounds good to me. Yeah. I mean, something comes in and you'll lock it up. Boom, boom. If and how it locks work, right. Is, is, is, is when you lock something, if another, another piece of your application tries to call that method, it waits there. Yeah. It's just wait, wait, and that's fine because imagine if you had a little database and you said, right, right. You want it to be in sequential order. You want it to do that and, and um, you want it to happen and if you had a hundred rights, the problem of doing it non asynchronously becomes a problem because maybe that'll take a second and you don't want to lock your UI. So you might be like task, spin it up, boom, boom, boom, blah, blah, blah. Right. Frank (12:08): Right. Plus it was nice was it was a nice encapsulation of a pattern that everyone was using. You yourself just said that you put locks around your SQL light use. Everyone was doing this because we all ran into the issues with SQL light hitting it from, you know, either multiple threads or multiple file access, whatever. We've all run into those issues and we've all come down on the side. We're just going to put locks around everything cause that just makes life better. Um, so yeah, it was a good implementation because it was simple, easy to understand, gave you a sink kind of for free. And it worked. It worked well enough, James. Well enough. There are just two issues. Um, do you want to go with the issue that I've already solved or the issue I still need to solve? James (12:55): Most of us do. Um, let's go with the issue you solved first. All right. Because I think it will be learned your lesson already and Frank (13:05): we can start from there. Cool. Well first I have to blame a friend of ours, perhaps a friend of the show of ours. Uh, a person named Clancy. That's not actually his name, it's just what we all call Clancy. It's all Clancy's fault James. So Clancy comes to me. Clancy has an app called G music or had an app, has an app. I don't know what it is. And he is a performance freak like myself and I love him for that. And he found ways to get sequel light to operate in a very performant manner without using so many locks that we were using. The problem being, let's say I have three threads that want to read from the database and no one wants to write to it, well that should be a safe operation. Three threads should be able to do it all at once, but because of my lock, that would never happen. It's always going to be whatever, one thread after another, after another. Clancy is like not good enough. Not good enough. Have you ever had to deal with the side of his personality? James (14:10): I have. I know the Clancy, the clients and eight or 5,000 and uh, yeah, I could see his demand and desire for it Frank (14:17): for it. Yeah. So it turns out there is a magical option that you can pass to SQL Lite called full mew techs. Now, this did not exist when I first wrote my library, but it exists now and full new tax is pretty much exactly what we were just saying. Talking about putting a lock around every time that you, you use the database, except this time it's built into the database and it's smarter and it knows that it actually can do multiple reads at the same time. Those are a hundred percent safe, things like that. So it kind of actually allow multiple reads, even though it's called a full new tax. All it's saying is basically we'll handle the locking. You don't have to worry about the locking anymore. Right. That is neat. I like that. I like that. Yeah, so they bake that right into the library and that mat in my library, I could take away my locks and the whole boy. Frank (15:20): So number one Clancy was right. It totally worked. Units test passed. I had version 1.6 in beta for over a year. People are like, yeah, it seems to work. Seems to work fine. Chip it already right. Ship it. I think we even had an episode where I was saying I really need to release this fix, but I'm nervous about it. This is the release. This is the thing I was nervous about cause we took, we took away our lock in favor of the database law. Uh, scary, scary times. Um, so it shipped and it worked. It works fine. Fine. James, we'll call it 99%. I'm not a hundred percent really buying that. Uh, that it works fine. I'm not the, what you're putting down here is that instilling confidence in me on uh, on, on the tone of your voice if I will. Okay. I shouldn't be that because, um, there was a bug with it but it wasn't as bad as bug as my tone I guess is betraying. Frank (16:28): I just hate bugs, you know, I can't stand bugs. There was a regression and it is the unfortunate case where I think this library is one of my best unit tested libraries out there, but just did not have a unit test covering this scenario. And it ended up not really being the fault SQL Lite, but just, you know, multi-threaded code is hard. Yeah. And so, yeah, I had this regression, it was a weird regression. So what would happen is if you queued up to asynchronous operations and they both happen to use a transaction and they got queued and execute at the same time, that might sound like a common scenario, but it really doesn't happen that often. My computers are fast SQL Lite. It's fast. You very rarely have two things that happen at the same time. And it turned out and all the tests, I never had two transactions happen at the same time. And yeah, guess what, people put this thing on a website, websites, you know, web servers are busy, busy little buggers and bug, uh, triggered it. Makes sense. So, right. Like, yeah, makes sense. Yeah, makes sense. You have a is very different than a mobile application in which, you know, I use, James (17:50): you know, SQL Lite and I hit save and I write something to the database. That's pretty much how it works. Um, so I can, I can see that, uh, that might cause an issue. Yeah. Frank (18:01): Yeah. So that one was nice because at first I was really stressing out because, you know, it's, it's a sink code. You really don't want to mess it up. But, um, the solution ended up being very simple and elegant. I could put a simple lock over transactions. They won't affect anything else. Everything's going to go through smoothly because thank goodness I have a decent API on there, a nice high level API. So I wouldn't break anything. The right things were private, which is an issue I have in this library. I made way too many things public and so I'm afraid of always breaking someone else's dependency on me. But in this case I was able to do it only modifying private stuff and it was such a relief. My only regret here is that, um, it took me so long to fix that regression because it was just a flat out bug mistake and just flat out our testing cover it. Embarrassing basically. Yeah. James (18:55): So once you figured that out, did you write a test for it? Frank (19:00): Oh yeah. Of course. Come on, come on. Yeah. Yeah. The test is simple. You just, you know, start a transaction, make it sit there and start another transaction. Make it sit there. They collide very easily that, that's databases. At least they're easy to unit test. Thank goodness for that. Um, but it's funny because that leads into the next section whilst running, writing that unit test. This other unit test kept failing. James randomly, you know, the way unit test should fail just sporadically and under random conditions. Isn't this? When you want to give up software, you're just like, I cannot write software now. It's proven. The world is telling me something. The red dots are telling me something. So it's driving me nuts. This other, um, this other test keeps failing. Well, that turned out to be, um, more assumptions and down a dark and dirty path called synchronous locks in an async world. Uh, Oh, bump, bump, um, or I think what we called it before was calling. Don't ever call dot result. James (20:09): Yes. Don't ever call dot result. People don't, don't do it. Don't. I know you want to Frank, I know you want to do it. I know you want to do it because you read somewhere that you can call that resolve. But guess what Frank, you can't because you're on the user interface interface thread and that will lock it. You can't do that. I think it's because I'm not positive here. I feel like people want to use dot result because maybe they're used to backend systems or command line applications where like that's kind of reasonable and rational because there's not really a UI thread. I'm on some background service and it handles that automatically because I'm like, okay, I don't want to leave. I don't want to do anything to do dot result and I, I can't be in a async task at this point or often. Sometimes people will do it because they're inside of a click handler, which it can only be avoided. You can't change the signature of a click handler. It's just you can't do it. Um, so you're like, Oh, what do I'll do? I will dot result it. And then what happens, right there is it locks the UI thread. Frank (21:17): Well sad. Um, I use it all the time. Wow. I'm terrible. I'm terrible. No, you, you named the UI thread and honestly I always thought that that was the biggest danger to yeah. Uh, don't call that resolve cause you never know who's going to call you chain reaction, all that stuff. Oh. Also I think one of the arguments, another reason why people don't use, or at least I don't personally use it in some scenarios, um, async and awaken feel kind of viral. Like you put it in one function, now the caller needs to have it. Now the caller needs to have it now the color it needs to have it. And it's just like, Oh my God, I don't want to continue. You can continue where exactly. I was coding James (22:00): the other day, something on my live stream and I'm like, Hey, and I'll just continue with and ignore everything. My new favorite thing is you can do continue with and if you don't care about the result and you can use underscore like the underscore and then that's a throw, just throw it away. You don't even care what it is. I don't even care what happens. Just it's a fire and forget. I don't care. Frank (22:20): Okay, so you say you don't care, but you really want to check. Um, is is faulted or is succeeded or succeeded because it has an exception message that you're going to lose. If you don't do I care? Okay, you will get the bug report. So I figured, as long as I'm not blocking the UI thread, who cares if I sneak in a little bit. Dot. Wait here a little bit data result there, it's fine. Especially because I'm coming from the mobile world. I know exactly the performance characteristics of this device. I know I'm going to have about 16 threads in the thread pool. It'll go up to about 32 or 64 if it's really freaking out. But I don't have about that many threads in the thread pool. And you know, if I do a dot result here, it's going to wait like milliseconds. It's not going to be that long. You know it, it's not that bad. And I was right. It's not that bad. Like it really, you can get away with it. In a surprising number of circumstances, you know, where you really can't get away with it. James, where does that on wet web servers, when people are putting this thing on web servers that do a sync hi, why can't you sell? You would think that you'd be able to get away with it James (23:34): because web servers kind of are always dot. Resulting and dot. Not caring about stuff in a and doing all sorts of stuff now. No, Frank (23:43): well they shouldn't be. Um, so in modern asp.net core, they've been really good about making asynchronous versions of pretty much everything. Yeah. Everything that you used to be able to do in a synchronous version pretty much has an async counterpart these days. And they didn't do that just to annoy us. Um, they did it because they want crazy performance on all those crazy server performance charts and you're not going to get crazy performance by using operating system threats. They're just not that fast. They're resource hungry. There's lots of context switching involved. Every time you bounce from thread to thread, it's just not going to happen. And that's how old web servers used to work as threads and processes. What we do now are tasks, tasks, tasks. Yeah. And tasks are nice because you can have technically an infinite number of tasks, whereas your resource bound for threats. Frank (24:42): So got it. Got it. Yeah, makes sense. So the asp.net world said please for the love of God, if you're going to make a high performance website, do everything with async. It's better. I know it's annoying, but please do it. And if you follow all the, uh, asp.net people on the Twitter as I love to do, um, there are a lot of smart ones out there and I'm don't want to do it this service by naming just a few names and not others. Um, but who was I following? Mr. Fowler. David Fowler, is that his very smart individual, a very, very smart individual. And he was saying something about like, darn it, people stop putting synchronous code in our web servers. You're breaking everything. I'm like, Frank, that's my gut reaction. James. My gut reaction is I do it on iOS all the time. It's fine. We'll go, what's wrong with your web server? Frank (25:37): It can't handle it. But then James, he started explaining and the news just got darker and the sky got darker and like the sunset, I think that's why the sky got darker. But you know, things just got depressing for awhile. Can I name you some of the depressing things he said? Yes. I would like, give me the recap here because I was trying to look through this a little bit and uh, I liked, there's charts, there's graphs. It's hard. Oh my God. It's crazy. It's crazy. Um, but I will summarize all of this by saying don't put synchronous locks in asynchronous code because of something that is called thread pool starvation. The thread pool is our little abstraction of we want to run some code. We don't really care if it runs right now, but it should run pretty soon. Please go run at.net. Put it down the thread pool. Frank (26:27): It's what we had before. Tasks basically. But it's also what tasks use to execute their code. So there is a relationship between the two. The problem is the thread pool is dynamic because threats, you know, their operating system resources, like I said before, they're resource limited. You only have so many of them and things can really slow down if you have too many of them. So it's this real balancing act the ThreadPool has to do and deciding how many threats to have at a time. So imagine a scenario where a server request comes in and it uses SQL Lite database, which has a little lock, a little synchronous lock, shouldn't take long, but it's there. It's the loop, it's just a little Wheelock and then another request comes in and then another and another in cash. Darn it. These requests keep coming in, 500 requests come in and all of a sudden we've starved the thread pool because SQL Lite has decided I'm going to eat up an entire thread while I wait for some other threads to finish. Frank (27:31): While it is supposed to be a task based library, deep down implementation details, ugly stuff, it's, it's forcing things to be on threads and I guess that's the fundamental problem with synchronous locks and async code. Yes. This makes sense to me. So let me, now let me make the dark picture darker. So you would say, well, okay, maybe things would just, you know, work themselves out. Give it enough time, give it some coffee. Hey, you know, your servers doing stuff. Just scale out. Just scale out, scale up, scale out. Yeah, just kick the server reboot at once. Yeah. The problem is it just cascades and gets to a point where it just can't recover. Like these are just cascading conditions. They are irrecoverable to get from their rare, it should never get into those conditions, but it's totally possible. And this is, I guess is why I also think math, whatever, should always have something that just reboots your server every hour anyway. No, it's a quick way to fix bugs. Just reboot the server every hour. Frank (28:40): So that, that just shocked me because I had always just considered it was a get a sip of coffee kind of problem, not we're going to destroy the world kind of problem. So to see that this thing can actually get to that point is really sad and you're like, okay, I felt a little bit of shame for having synchronous locks in my async code, but now I feel like, I'm sorry I'm breaking the internet all of a sudden. That's how I feel honestly. Now in this, in this call, were you specifically called out for like your library? Oh, no, not at all. This is me creating problems for myself. I see. But you know what it is. Um, I've been wanting to use more SQL Lite in my own web servers because honestly it's just easy, you know, and just make a class and things just work. Frank (29:33): It does migrations for you, all that stuff. It's very reliable. And so I've just been wanting to use it and more of my own web projects. And so recently I've just had an eye towards making sure that it runs well in a server environment, not just hoping that it runs well and a server environment. Got it. Got it. That makes sense. Can I get another real quick horror story about this? Yeah, go for it. I just like it. Pretty much. This is me nodding and agreeing with all of your whores and everything that you've done wrong and Frank. So it's confirmation. It's like we always knew not to do this, but this is proof that it's bad. It gets worse. It turns out that the jet, the thing that compiles your code is uses the thread pool. And so if you starve the thread pool, you can actually stop the entire runtime because it's not able to compile your methods in time. Frank (30:30): How's catastrophic James? It's, I guess you're a spiraling. You started to spiral out of control slowly, but then you spiraled out of control so fast that you stopped everything. Yeah, and I want to stress, this is not going to happen in a mobile app. Now this scenario is just so unlikely a people only use your app for five minutes. You know, it's just not going to happen. But it's possible. And you've read through the issue. They're like someone recorded it. They have logs and graphs and things like this thing is happening. So I guess this whole episode was me saying, I'm sorry. Every time that I've put a synchronous lock into async code and said it'll be fine. I guess I was lying. I guess I was naive or ignorant. I don't know even which one of those adjectives to use. I just feel so bad about it. Frank (31:21): I'm not bad enough that I've actually fixed it yet, but I plan on fixing it this week or next week. So you didn't, you did fix some issues though, correct? Yeah. Yeah. Because uh, yeah, the, the primary goal for me was to make sure that it runs well on a server and it does, it really does. It's fine. Um, this is more like, does it run well when the server is dying or you know, when the server is being, what's the modern equivalent like we used to have slash. Dot. Like what's the, yeah. Well, you know, when a lot of people are using your server, I just don't want to be the bottleneck. I don't want to be the reason that David Fowler has to read some bunch of logs and graphs. That's true and well, and, and to be honest with you, I just want to let you know that monkey cash, the ultimate caching library for all people that love bananas went with the tried and true approach of the using synchronous with locks. And I think using synchronous with locks continues to just work just fine and it's never gone astray. Yeah, there's a simplicity to it that's just pure. I mean that was how SQL light dash net worked all the way up to version 1.5 or six. Yeah, there's a beauty there. The problem is you have these performance freaks out there like Clancy, let's, let's bring this all back to the real main point here. It's all cleansed James (32:45): Clancy's fault. Yeah. So this makes sense because he would never use monkey cash because if he said get or right, it would, he wouldn't be able to do it multiple at the same time because it's impossible because I lock it. He'd be very upset. Frank (32:58): So you've actually dealt with the exact same issue with him except you stood your ground and I let him win for the performance James (33:06): and I said no, it's a caching library. Clance if you want to use the database, use the database. My favorite is like I actually in the SQL I net code, I have select statements. I didn't even use the link query language. I mean why don't I do this? I'm like yeah, I'm looking at it and I literally have select star from banana where expiration date is less than question Mark. That's right. Frank (33:26): It's fine. It's fine. Actually a lot of people use the library in that way. A lot of people use it as just an easy way to um, put in their own queries into the database. Yeah, it's a very common use scenario. I would actually love a breakdown of who's using the link part versus the query part. James (33:45): I always use the, Oh, you know what, I always use the link almost exclusively and I forget why I did this. I believe I either reviewed it with you or I reviewed it with, I actually do. I, I'm looking here. Oh no, no, no, no. It's funny because I'll do like a query where I'm like, give me all the bananas and how monkey cash works is like you. The object you store is, is a banana and the thing that you're storing it in is a barrel. So you're putting bananas and barrels and it's called monkey cash. It all makes logical sense. It's funny because what I do is I, I do like, uh, I appear to be doing a query of what is this, what is this doing, get keys. And then I do a query and then I do something like if it has a flag and then I do a link query on the results. So instead of doing it in the link query, like I do it later. For some reason I don't know what I'm doing. What am I doing in this library is great, but I've also a little bit of a waste. I've always used the link a chorionic cause it's been very, very nice. And I think I was doing this cause you're like, Oh this will just be faster or something like this. Or maybe someone else did. But Frank (34:53): yeah, uh, yeah, I would usually putting the query into the databases fastest. It's a quick little query language and all that stuff and there's a little pause in the beginning. Oh, so this was a fun adventure. Oh, I should go back and say, do you remember I had that weird unit tests that kept randomly failing? Well that was the unfortunately named stress async unit tests and it turned out what I was doing. Um, and actually this one was causing me trouble before in CGI. Like the CII build would fail sometimes cause I run the unit tests in CIA, but then I would literally click rebuild button and then they would pass. Isn't wonderful. Oh, interesting. Yeah. Well it turns out, I think I discovered why because it was a very poorly written test by yours truly that allocated a 500 threads, actual operating system threads. Frank (35:52): Now in windows you have a 2000 thread limit and I cut 32 bit process. I don't know what the limits are on Linux, but I'm sure it's running under Docker image, all that stuff. I'm sure it has limits. So I think what was happening was I was actually starving, like the operating systems ability to give me threads. I switched all that code over to use async. Like it should have been written async tasks and it passes almost instantly now and it has never failed in CAI sense. So I guess welcome to 2010 write your code and Hey, think it's makes sense. This makes sense. Yeah, I like that. So I'm going to go to the synchronous one, but you know, that's me. Okay, fine. My life is going to get your full, mew Tech's not going to get your read two reads at the same time. Frank (36:44): I in on purpose, on purpose. Actually it might be a good time to rethink how I implemented the thing is how I implemented monkey caches, that all the, all the methods are synchronous to begin with. So they are, I'd have to introduce a sink and an asynchronous version of it and that seems like a no bueno. So no, I don't think there's any point to it. The only scenarios where this comes up, it's where you're really hitting that database. Um, hard from both sides. So like if there's a website, you know, give me a query that returns a thousand things, a query that returns a thousand things, um, that would be common. But I think monkey cash, it's always single key single value kind of stuff. I think it would be, yep. Makes sense. Plus it's the mobile world where everything just works and you don't have to deal with all this server nonsense. Frank (37:31): That's right. It's a, well actually, surprisingly enough, I support, um, asp.net core with it. So what's your, what's your user base we should measure? I wish I had the stats actually. Gosh, if you get, gave us some stats like that, what kind of product is our library being installed into? Would love that would be fascinating actually. I would be super fascinated. It's like understand that. Yeah, because all you get are the bug reports. No one ever like creates an issue. Just wanted to say, I love your library. Your library is great. It's true. You only see the failure cases and I never know. Uh, yeah, it's, it's hard to tell. Like I assume more mobile users are using it then web developers. But there's a lot of web developers. I also ponder who are the people that trust a library called monkey cash. It's your name. It's your James [inaudible] is who I am. No one knows who I am. It's the heart on your tee shirt includes us in that. You have one barely, James (38:36): barely. Oh well thank you. Frank (38:40): Thank you for listening to my story about open source woes, life lessons, feeling guilty for not knowing how things worked 10 years ago. James (38:51): No, it's not your fault, Frank. Here is the situation. You learn something in the process. You got a story out of it, you fix some things, you improve some things and you'll continue to improve every single day. And that's just life rank. That's just how life happens. And you're great and we all love you cause you know why? Cause we all use your library and we wouldn't be anywhere without it. That's the thing to remember. Like, even like I look at, I look at, um, like my media library, which I really need to like either rewrite or completely update and take way, amount of time and yeah, there's tons of issues open with it, but for like a majority of people, it actually works just fine for their use case. Um, and that kinda makes me happy. Like when I see someone that's like, Oh, you know what, it doesn't, it doesn't have everything that I want, but it got me that was able to shift the application and I'm pretty happy with it. Bingo. Bingo. That's a good, yeah, that's a good day. Frank (39:48): Yeah. Ah, that's a great way to end. I love that. Yeah. People actually using the library. James (39:57): Yeah. People actually use your library. I mean the thing has millions of installs, so you're good to go. Frank (40:02): That's just a million people that I can upset. James, I'm a glass half full empty and it's getting emptier by the minute. James (40:10): No, no. Well, let's end on a positive note because if you like SQL Lite dash net, guess what? You can also sponsor the whole thing. There's a sponsor button up there. Cause I think Frank, I mean if he, if he hasn't done it yet, he has a weak on this recording of this podcast to sign up for get hub sponsorships. And you could sponsor SQL Itasha. I would, I would give Frank my money if he was to do that. So let's hope that Frank does that. And you should also check out all of his awesome other projects like food, get food gets awesome. If you're like nougat, it's like nougat, but with an and set of an end. So that's pretty cool. You can just check that out. And you should also check out his other applications like continuous continuous.codes. That's an amazing ID on your iPad. He just updated it to C sharp eight and F sharp four dot five and Xamarin forms for dot four was XAML support. That's pretty rad. Pretty much. We love you Frank. And that's going to do it for this week's podcast. So until next time, Frank (40:59): I'm James pots Magnum and I'm Frank. Thanks for listening. Peace.