 Welcome. It's the 22nd of June, 2022. This is Google Summer of Code, Git Cash Maintenance Project, Rishabh and Rishabh. Welcome. Let's get started. So Rishabh, what topics would you like to bring up and let's go through them? First thing, I have a failing test on Git plugin and Git client plugin. It's specific to a version of Java, so I tried debugging it, but I couldn't, so yeah. Okay, well, so let's take a look at it. All right, so, and you say it's a failing test, consistently failing on ci.jankins.io? Oh, yeah. Or is it? Okay, I don't see a failing test, but the job fails. Interesting. Okay, so let's get a look at. Okay, so the job failure is because the agent died unexpectedly. So let's see if that's what it says. Oh, okay, yeah, in this case it's saying, hey, it's attempt to launch the Java 17 agent failed completely. Okay, so the easy solution for you in those cases, close and reopen the pull request and that will relaunch the job if you don't have a rerun option on the checks page of the GitHub pull request page. Let's do a comparison here of what my page has on it and what your page has on it. So I'm going to share my screen. So on my page, so this is the pull request and here, let's look at it, let's look at a different pull request. So on my pull request page, for instance, with this one, we'll see in the checks tab. There is under ci.jankins.io a rerun link, but I bet if you check your page you may not have that rerun link. Right, so the solution for you then it's not a particularly attractive solution I wish GitHub allowed us an easy way to grant a permission that would let you have the rerun flag but not give you full merge permission but they don't. So what you do is you close the pull request and reopen it immediately. Okay, I'll do that. I think the Git client plugin is running again, I'm not sure how. Yeah, I just clicked, I clicked the rerun button. Okay, okay. Right, so and Git client plugin should complete its testing quickly enough that before our hour ends today we'll see the results here. So while while that's running let me go grab a copy of your pull request. I'm going to start evaluating it he'll look here locally just to be sure that get client. Okay, because I can usually get results very, very quickly. Alright so GHPR checkout. This one. Maven. Let's see. I'm just going to be sure that I've got that. Okay, good. So there's something to do. Alright so Maven clean. SD for count equals one C verify. Okay, so that can run in the background while we're while we're talking. I've added maintenance commands in the Git client plugin but I'm not able to use it in the Git client in the Git plugin because of that incremental thing because the tests were failing I couldn't try that. Can we try that once? Absolutely. Yeah, so let's let's let well first let's let's get this this thing confirming that the tests are passing while it's running. Let me get it running on another location. And you should be able to use an incremental that's in your local repository. You can't push that because nobody else will have seen it, but we should be able to let you use an incremental I thought anyway. That's locally available on the same front it'll come from the same Maven Maven cache where it writes everything else. But actually tell you what let's try that what we're going to do is on this other computer here. We're going to do an incremental build of it. Get the version number of that incremental and then try to use that on a get plugin. That's the thing only to like my my thing right which I do correct right this would this would only let you do very short term development because as soon as you share it with somebody else it would require that they had to have built the plugin as well. And built that built the dependency as well and you don't you don't want to put that under the people so so this is just a very short term stop gap while you're waiting for CI Jenkins.io to successfully build your pull request. Okay, so let's do this. Let's g hpr list g hpr checkout. 862. Now I'm curious, can you hear in the background my granddaughter crying. No, no okay I wasn't sure how my microphone did it at retrieving the sound. We have grandbabies who are visiting my house and we're having a lot of fun the two year old right now is a little tired and doesn't want to go to sleep. All right, so let's see g hpr checkout 862. Maven clean minus d skip tests, verify install. And now let's see and the tests have passed good. Okay, so Java 11 tests past and the one that had a failure on CI Jenkins.io was Java 17. And so now I'm going to use Java 17 and do the same thing. I don't know any reason why tests would pass on 11 and fail on 17 we've not seen that. In this case, the I think the works. Okay, so Java 17 could not initialize class. Huh. Well now that is. I didn't add any new. Right, right and and I know that this was running. So just a minute. Let me. That's very interesting. Okay, so Java 1703. And admittedly I've got a few cores on this computer so it's, it may just be that there's a problem with ID is no very interesting. Is this the first check. I actually I'm pretty sure that if I look at get client plug if I look at its Jenkins file is running it every time. It is. Oh, oh, oh, of course. I'm foolish. Right. So, well no way to say in your palm dot XML file Jenkins dot version is. Oh no it's outdated. Okay, it branch. Why is wait a sec why is Jenkins dot version so badly outdated. I just updated it to require a new version. That was only in, you know, the good plugin. I didn't. Okay, good, which is which is fine. Your change doesn't require the newer but but in order to use Java 17 I must tell it that I'm using a newer newer version of Jenkins so this is where I should do it like this. I'm using a newer version of Jenkins 6 because tomorrow it will be 346.1. Okay, so now we're going to say me even clean minus D for count equals one C okay sorry about that little mistake on my part. I should remember that full Java 17 support in the tooling is not ready until at least Jenkins 2.34342 I think it was to it took a while before we had full Java 17 tooling support. Okay, in my other example, I've built a an incremental. Now, how do I deploy the incremental. That already deployed who she can reshoved you remember. See, we should read the directions there that's why we have documentation just a minute. Jenkins here we go incremental. There it has been completed. Okay, so I did a maven at home get maybe. Now this isn't telling me what I was. Oh, here we go. No, I wonder what that means. Okay. So I need to I really want to deploy. Oh, right. I just said it. Maven deploy. I just want to refer this to to the repo that Jenkins that I owe a repo to that Jenkins CI.org and I don't really want to run tests again. Skip tests. Now I should be able to while we're doing this I should be able to read this. And it will tell me that. Maven deploy was the thing that I wanted to do. Automatic deployment of commit incrementals. Yeah. So here it is said it says okay. If you had enough permissions you could run this to put push your latest commits. Okay, that simple solution did not you right. Okay, I'm this is him describing. Incrementalified. Alright, so enabling incrementals that's done create a pull request wait for checks, obtain the okay so this is telling us how to do it with CI Jenkins.io it's not telling me how to do it with a local push. Okay, so let's see if we can get it from CI Jenkins.io. See I get client plug in and we want the pull request that was most recently successful. Nope. That is currently running then. Nope. Okay, so maybe it's the newest one. Oh, there it is still running. Okay, good. Alright. So we're still in process. Did we get a Java 17 machine running we do okay so we're waiting for windows the slow one. The other two have been successful. And we unfortunately don't have artifacts yet so we've still got to wait. Okay, so this is continuing. I still think ah yes, I have permission and I don't know if you do who should cash but I have permission to do a maven deploy. And so what I just did was I pushed this incremental up to maven Jenkins dash CI.org I pushed it up to the repository. And as I pushed it. I should now be able to change to get dash plug in and use that highlighted thing. Can you can you read that text. Is that a little better. Okay, yes. So now if I go to get plug in. Let's see the list of pull requests. We'll check out this one. Well, we'll check out that one. Okay, now. Good. Get dash client. Okay, so here it is. And we're going to say version. I've lost it from my copy buffer. Where did it go. Here it is. Okay, let's try it. Okay, so that works at least this far it worked. Okay, so what is this saying no point. Oh, okay. There is a problem here. And the problem is that the tests are written badly. They should not depend on a well known file name in a public directory slash temp slash dot get is not a place to do put things. Now I don't know why it does that. So that'll need some investigation but whoever in the tests is writing to slash temp slash dot get that's fundamentally not allowed. No, it's still got something going away to sec. There was this other mistake I was making wasn't minus the Jenkins that version equals 2.346 like that. So that's running. And this thing ran to conclusion and now I've got to get plug in. So would it help if we prove that those versions are working or who should cash is this already enough. I think this enough. I've written the maintenance comment but I don't think we can use it in the login. They have to access the client and then use it so I think this is enough. Yeah. I mean, could we could we do something like make a call to it. The call is never exercised. Yeah, yeah, we can do that. Okay, so there is a method maintenance on get client. So if we were to make a reference even if we make a reference to get client dot maintenance in something that's never called it should, it will either fail the compilation which says we made some I made some mistake, or it will pass compilation. Okay, if you do it to the, you know, get, you know, this CLI get a thing like the class, then you can even run the maintenance command because I added the code for that. Okay, well so let's let's try this so I need something that uses get client and yeah let's look inside get SCM and see what's there. You should have an instance of a good client. Exactly. So, so I've got to create somebody must be returning or dealing with a get client like this one. Yes, right. So I've got to get client there. And if I said get dot maintenance. Mad, you're going to make it real. Yeah, I was going to say something rubbish. You're going to make it real that's even better okay. Okay, so, so now we're going to make it real and do a compile. Now this certainly will not be happy to run but we don't care about running right now right skip tests, and let's do a verify. Okay, so that was successful, which tells us that we were able to reference get dot maintenance because I need to update the version every time I send a sender you know, when I push my code to the get client. Do you need to update the version not sure what you mean, like the palm dot XML file made why need to update the client plugins version every time I push it, like, if there is an if there is a relevant change in the get client plug in. If there's a request that you're that's being evaluated, then you want to update to that if you if it's if the change you made was cosmetic or not relevant to the thing you're working you don't have to increment. You don't have to change this version number. Did that answer your question who's your cash I'm not sure that did. Yes, yes. Okay, so. So what I'm going to do is I'm going to go ahead and push this to your branch so that you've got an example if that's okay. Yeah. And if you would be willing. Would you could you try incremental get client build. Could you try downloading this while we're on the call together here and try to compile get plug in off of your development branch. Jenkins dash 13493. And I hope it will just compile for you directly, because the this incremental version that I pushed is visit should be visible to you from repo dot Jenkins CI dot org. So you want me to compile it right. And then do a maven clean verify or a maven clean minus D skip test verify. Yes. Okay. That's running the project. Good. All right. And it looks like the get client draft pull request has also completed successfully. So we can then have you. We've confirmed it builds with the change I made, then we can have you switch to use the, the, the incremental build from CI dot Jenkins dot IO. That gives you practice in doing exactly the same set of steps. And has the compile succeeded. No, it's taking some time. I'm not sure how long it takes. What is the. Yeah. Okay, now, now you need to do the next step, which is open up the pull request. I'll paste a link to the pull request CI job. And we'll have you. Download let's see where's the chat window here it is. Okay, so here's the CI job. And on that page, you'll find five different artifacts listed. For three jar files and HPI and a palm, you want to grab the basically what I do is I copy the URL of the HPI file, paste it and then throw the things away that aren't specific to the version number. Now I need the version right. Oh, that's correct. And so the version number here is three dot 11 dot one dash RC 3079 dot long string of numbers and letters and underscores. I have to pay this version. Yeah, so you put that into the palm dot XML file of the get plugin. Okay, yeah, I added the version. And now I have to again now. Now what do I do now I directly build it. Correct. So you modify the palm dot XML file. Build it again we know that succeeded with the incremental that I did. All you're doing is changing to use the incremental that CI Jenkins that I did. Okay. Yeah, yeah, the build and success. Good. Okay, so commit it and push it. And now I have to come in and push this. I'm sorry now you what. Push this. It would be good if you push it because that way you know that you're working on an incremental. No reason to lose track of the information you just learned. Let's hide it. Let's hide it. Let's put it inside the plugin. Yeah, I pushed it. Great. I have to keep doing it whenever I do any changes related to the maintenance and the client. Right. Right. If you have to update, if you need a new API from the get client plugin, you'll have to change that or if you made a significant change to the content to the implementation, you'll need to change that in the get plugin. I tried building the project and then it shows, you know, could not resolve dependency for the project. Sorry, you say it shows an unresolved dependency. Yeah, yeah. Okay, so that may mean that you've got some slight syntax error in the, the version number that you copied and pasted me. Okay. I'll check that out. Well, and this is a good time to check it now. Let's don't let's not delay because we want to be sure that you're able to successfully use incremental builds. Mark, I had a question. If is it possible for me to have two controllers for a Jenkins instance for a particular Jenkins instance is it possible for me to have two controllers and multiple agents. When you say two controllers and multiple agents, you mean something like a high availability setup where you'd have. Yes, yes. Yeah. In a distributed environment, can I have separate instances of controllers running in separate machines, but for the same, for the same Jenkins. Well, so Jenkins doesn't have, doesn't have a way to do concurrent execution you can do, you can do rapid fail over where you store the Jenkins home directory to a shared file system to a shared high availability file system and then when when server a dies, you switch to server B but you have to start server B after the death of server a. Did that answer your question, Rishabh. Yes, so the case is always going to be that I'll have one control instance and multiple agents. Correct, that is correct. You will you will have one controller and zero or more agents. And we hope that every user will have at least one agent but zero or more agents for sure. The header which I get here is the failure was cashed in the local repository and resolution is not yet in it. Right and that that says that. So let's try that. Let me get a. Okay, so let me get the same thing on mine. Let's see am I sharing my screen still. Yeah. Okay good so let's. I'm going to try the edit here. See link address. Now I'm going to delete a bunch of stuff to get down to just the version number. Oh interesting. That is the exact version number that's stored there. So you got the exactly correct version number for cash I don't know why it's not working. Interesting. Find out why not. Logs we would see even pulling it from the repository thing. So I guess, which case can check if this particular jar is being put from the. Well, but, but what we see is the job was successful, at least on my screen I see that the job was successful. We need to read the build log because there there are conditions under which, for instance if it's not up to date with the master branch it may quietly refused to push a copy to the repository. Let's see if it tells us that skipping deployment as no artifacts were found, typically due to a PR builds not up to date with its base branch. Okay, so. All right so we're going to update this with the. Oh no that's interesting. So who should cash when you did your, your build on the get client, your base branch was quite a bit out of date. So let's do it get push. So we'll need to wait another 15 minutes or so so who should cash your, your build cannot work yet because the. Okay, so get revert incremental build is not available yet. Not available because the base brand the, the whole request branch. Did not include the full contents of the master branch coming soon. Okay, so that now should let us. So we want to see 1277 and the checks are running. Okay, so here we see that the checks of PR job 1277 are running. So 15 or 20 minutes from now we'll have an incremental and it will publish. So who should cash what was happening is we can read it in the log here for the job. It says in build number 26. Oh, no wrong one. Sorry, we need to look at get client plugin. So here in pull request 862. If we look at the preceding job, and it's console output what we'll see is it says skipping deployment as no artifacts were found with the expected path. So what that's telling us is hey we are not up to date with a base branch and so I made that change pushed it, and now it's building here in number five. Sorry to have taken 40 minutes on this topic are there other other topics that are important to you for your cash. And specifically about the locks I'm not able to add locks to the caches, because I don't have the you know you are a lot of the string, the concurrent hash maps takes you are less the key and the lock as a value. So if a repository doesn't has, if the repository is not present in the hash map, the, the cash is added to the hash map and then it's logged. So is there a way to you know, get the URL so that I can add it. I think, well okay so let's. Let's let's take a look at that together. It's abstract get a CM source right. I even added the code to get all the, you know, cash is on the controller. So I need a way to you know, add lock to it. So, so since you've done that I think we can use that as the basis can we so let's let's go looking so. Whoops, let's use a way to see the differences. So have you pushed your any changes to the. Okay, so bunch of new imports. I've removed imports. All right, get cash is dirt. Okay, so you haven't yet provided you haven't yet pushed anything that that iterates over the over the list of caches. I added the way, you know, because I just needed a list of, you know, caches, so that I literate it, you know in the task executor class, where everything that I create a new thread and iterate through them and run the maintenance Okay, so, so the idea then here is somewhere in this you will, you will send back to the caller a list of directories that are the cash. Yeah, that right. Okay. All right. And then what you're saying is, you need a way to request a lock of that cash. So just add a locking method that takes the takes the lock based on the directory or given the directory then inside abstract get a CM source changing into that directory and make a get remote call to figure out which what the URL is of the remote. Oh, can you to beat once again. Yeah, so, so the idea is, okay, we need. We're, we're going to, you're going to call a method on abstract get a CM source that returns to you the list of caches, or list of cash directories right. Yeah. Actually, does it why, why not. But could, could it return to you instead of a list of cash directories, could it return to you a list of of repository remote repository URLs that then you'll use that as the argument to the locking, and it will figure out where the what the directory name is. So keep the knowledge of what the directory name of the cash is entirely inside abstract get a CM source. But then I need the URL so I'm not getting over you know to get the URL. Right. And so let's what if what if the URL where the thing you returned to the to the to the caller so okay so I had initially thought oh let's give the directory to the caller and let them iterate on but in order for someone to in order for you to lock the cash directory. As you said you need the URL of the of the remote for that cash directory right. Yeah. Okay, so remote. Let's find a cash method okay so it use cash locks cash locks. Okay so here we've got a cash lock and it uses this thing called a cash entry so my thinking is, we ought to return cash entries the list of all possible cash entries to you as a caller. And get the list of all possible cash entries cash locks. Okay, so. Okay. All right, so get the cash directory it says we've got a cash entry. And it's going to attempt. Okay, so. Oh no no wait a sec. Okay here cash entry in this case for sure cash is not a remote URL. It's being used as one element of a file so this is the name of a directory in caches right. Actually, if you call there's a method like if you search for cash entry there's a method which converts the URL into a hash. Okay, so it uses an MD phi hash, which converts the URL into this cash entry. Got it. Okay. So what you're saying is get cash entry. This method takes a remote and create and uses this to create the hash for it. Yeah. Okay, all right so so get cash and so if we. If we could reverse engineer like you know use the hash to get the URL but then that MD phi is like a one way algorithm you can't go right and and we certainly don't I don't see any reason why we would want to try to turn turn that hash code back into a remote. Why not just. Okay but the list of remotes must be somewhere right. So I figured how abstract data source is initializing this cash entry. You see it's it's trying to access the get remote function on 983 and get remote function is this method is an abstract method which places the responsibility on the implementation to get this remote URL so So my impression was that you could as a caller could have one remote URL per one SCM right. You could have but but but an instance of an SCM would have one at any particular given time would have one remote URL and if that is true, and you can't have all of the list of remote words from the SCM itself. And that is what you're trying to do right. Rishabh I'm not quite understanding so you're, you're saying that say that again why, why would you think that the, the list of remote, the list of remotes is not accessible. Because abstract get SCM source. First of all, one of the reasons why I think is that abstract data source is providing a contract there, which is get remote. And what we see, there is not a list of you are as for us to possibly get just one name that we can get the implemented can implement how they want to get that right they haven't themselves given the option for us to So within the context of abstract data source you don't have the name of those remote words implementation of abstract data source would have it or have the custom logic to get that. But I don't see it as a the methods signature doesn't give me the impression that you can have a list of you are there, you can get the list of remote words. When it start to think about it, my limited understanding, fundamentally abstract, any get get SCM instance or any SCM instance. If we initialize one would be initialized upon a single repository at a single time, right, it won't be running on multiple repositories, a single instance. It would check out for an example to check out one repository and do the work and then we would have another one for another deposit. So the relationship between a remote URL and a get SCM is one to one, not one to many. But I certainly agree with the relationship between a remote URL URL and a cash directory is should be one to one. Right, if there is, if we've taken in a remote, then it should have that that name plus its hash should give us that directory. I'm just not. Okay, I'm not. I'm not getting it. Why can't we just remember the remotes. Remember the association between remote and remote and cash, cash entry and return the list of remotes if that helps or the list of cash entries. Let me understand Rishabh I'm not sure what I'm missing there. I mean, so I remember they didn't get to choose it where we actually make a decision based on a cash. What we were doing was that we had we always had the remote name. We were able to get the exact cash and that we wanted and we could work on that right now when we say that we want all of the entries. We can get all of the entries but we want the remote you are and from what I understand is the different the design perspective. The implementer is supposed to know about the remote. It's not the abstract SCM source. That is what is my assumption. Well, and, oh great. That is the case that I don't see how we could get it at that. And with you in the current implementation, the, the abstract get SCM source, it receives receives the remote as an argument as it's constructing that cash. And then it relies on the caller to continue passing in that remote. But why can't we record the association between remote and directory. Add a new method to abstract get SCM source that will let us return the list of all remotes that are cashed. I agree. There should be, there should be a way to do this. Yes. I mean it just seems like if see what's an exit. I mean, one concept might be on startup of abstract get SCM source. It. So during object construction or during as a static initializer in abstract get SCM source it could iterate over the caches directory, looking for existing caches. And, and then we've got the list of caches and it can look inside each cache and ask for the remotes for that can the remote for that cash. And then we have an association between cash directories we have a list of cash directories and their corresponding remote. So Roushakesh, excuse Rishabh and my going going through this have it may be simplest if let's see let's try a let's try and okay we've got to have some place in this where it does a create of the cash directory right that's this thing right here. On my screen where it's creating the cash directory, if it doesn't exist. Maybe if we were to create a data structure, something like a list or no let's do a map of string and should it be a get remote. What does get remote return another string. Yeah, it turns it turns it. Oh, yes okay so there we go. The whole point of me asking the URL so that you know I can add the cash into the you know you know I can add that cash into that concurrent hash map and lock it so that whenever any other plugin tries to access it. They don't have access to it. That's the whole point of it. So why is it necessary for you to have the remote URL is the key for the hashtag. So that that thing gets converted to a cash entry, and all the other plugins also use you know cash entry as the key. So if we don't use the same key then there may be problems right. Right. Yeah, well, so isn't. I don't know that we okay just I think just thinking about this that all we need is a list is a list of strings that are the remotes, right, or call them cashed remotes. Isn't that already enough to. And then what we do is every time we, every time we we see a request to access a cash. We can set up somehow and add. Okay, at this point it's doing a cash entry. So conceptually, okay, it would be something like, hey. What, there is a data structure that allows only one of a thing. Ah, set. Thank you. Very good. Thank you. All right. Okay, thank you very much. Good. All right, so then, if cashed remotes, let's see, do we say that something like, if cashed remotes. There's probably even a method on a on a set that will let me just add it if it's not already there. This is the idea I was thinking if we just add. Cash entry is a bad choice but doing it right now because it's available. So now cash remotes has the cash entry, or if we were to do it at a higher level, it would conceptually have the remote. So let's add add the list of remotes, and then we create an access method that can read that list of remotes, and now you've got as a consumer you've got the list of remotes, and you can then ask to iterate over each of those remotes. And then one, so if anything is added to the cash remotes that isn't that like, isn't it like, isn't it like you know some other plugin is using it. I, I, some of when you say some other plugin is using it, you mean you think that there are other things that are accessing the cash without acquiring a lock. Like, no, like one minute. There's a method called like get cash lock. Yes. Yeah, so there's get cash lock. Right. There's this thing right here. Right get cash. Let's go find the implementation just a minute. Yeah, this one is that's what you're referring right. Whenever I add a cash entry isn't this like, you know, to get whenever I create a new cash on the Jenkins controller, then only it would be added or would it be added, like, and I get any of the caches, which are already present those caches also can I will those also be added into the cash remotes. That's what I'm. I think we want all of them to be done now to be added, but isn't there. Okay, so here for instance is do retrieve so it's going to do a retrieve of it's going to use command line get to add credentials, create the repository fetch and prune. So this is doing a get fetch and a get prune, or it's doing it doing a get fetch. That's now created a cash entry. And I would think what we want to do is take where is this this may actually be the kind of level where we want it so cash entry. Okay, now I'm not sure I understand this where is the URL. Oh, this is relying on it already existing. Is that correct. When I read this it looks like it's, it's assuming it's yeah it's doing the fetch without having. Well now is it. If you look at the method for get cash entry that method is going to be more. You say get cash entry, and it uses get remote. Yes. Let's see what get remote does it's. Yeah, and get remote is the is an abstract. I tried printing, you know, the concurrent hash map thinking I'll get something in it but that always returns an empty object. So that so like I feel, whenever a plugin is using it, it adds the, you know, a cash entry into the concurrent hash map, and then it adds the lock to it. Until and unless any other plugin is not using it I don't think anything is going to be added to the concurrent hash. Yeah but isn't don't we have the place we need. We have one of the places we need right here. We need to get the fetched remotes. If something calls get cash entry, but then the question is, is this this be called when an actual operation is applied by a user or is this for that the level of initialization on all of the repository so that you will have all of the I would think I think we want both right I think during during initialization of this class, we want it to check the disk once at least for all existing caches. And then any call to get cash entry if it's not already in the cash we want it added to the cash or added to the list of cash remotes. The retrieve word not be called for all of the list of the repositories that already exist within the cache when get plugin is initialized. Sorry and add and ask say that again. Do retrieve is the function that is actually calling this method. Okay. What I'm trying to think is, is do retrieving, when is do retrieving. Well it's, I just, I'm not sure I understand why the answer. I don't know the answer but I'm not sure why the answer would be would be particularly particularly crucial right any access, any access to access to the cash has to go through this get cash entry doesn't it. It's got to convert a a remote into a cash entry. So if we record it here isn't that already a good way to know oh here's a here's another somebody request a cashed a cash directory. And now I think we need a way of you know adding all the existing caches into the hash set. And that I agree. And for that. I think what we need is, and this I make what I'm doing here maybe cheating, because I'm returning a list, or a set that may expose internal representation so considering an organ for now then I think we need some form of static method that iterate over the caches directory. Assigning remotes are reading the remote reading the get remote URLs and assigning the adding them to the cashed remotes list. That's the idea I had is so when the class is initialized. It does that little bit of work to walk over each of the repositories in the cash is directory, extract their cash remotes and put them into this set. And then if there's ever access on. When access to get cash entry happens, it also doesn't add. And whenever I try running the maintenance task I can just iterate through these cash remotes, and you know get the at the lock to it and then run the cash get maintenance on it. That was my thinking anyway is if we just said okay let's let's remember the list of cash remotes. And okay when we start up, we have to iterate over all the directories. And then anytime there's a request to look at that. Somebody passed us a remote. And we can remember that one, just to be sure that hey, if the remote wasn't already know we want to make sure it's known now. That seems sensible. Rishabh Rishikesh. I'm thinking of. Rishabh I think you had some specific concerns and I'm not sure that this idea has addressed your concerns at all. Yeah, because I guess I need to run the instead and see how this is that is one of the easiest way to understand. So the way, if you look at the line one to five to the way we use the cash entry to create a new fight. What is the relationship between a cash entry and the list is a cash directive. My number again was one to five, three. 123 it may be offset by my modifying so it's it's this one. Okay, so it's good. Okay. All right, so and your question was what's the relationship between a remote and a cash entry. And that we saw right that I saw I'm saying that when it's creating a new file here it's getting the root directory and the root directory caches folder would have the list of all of the caches list of all of the caches right. Right this directory Jenkins root dir slash caches contains all of the caches as far as I understand. And then we specify a child of that. So we get this specific directory. And let's say I can't get the remote list of remotes from the system and I have the list of directories caches. I have access to that. And can I get the remote name on the basis of that information. You certainly, we can get the remote name. If we can get to this parent directory. Then all we need to do is iterate over each directory change into that directory and call get remote minus V. That means we depend on the call. So we need to search. We don't need to search for the content we actually do like if we are going inside we're creating the list and then I was, I was thinking that is how we would because I thought that if it's not possible for us to get out of the list of the most at this level, then that is how we will do. But I guess what you're doing should give us the list of. So it's going to be an exercise for me mark I mean I theoretically I, I think I have a doubt here and probably if I run the instance I'll be able to see if you know how abstract it is so it's actually like this. I think we wouldn't need the URLs anymore if we get you know all the cash remotes in that has set because once we have the cash entries like the cash remotes contains all the cash entries right. So once we have all the cash entries we can just iterate over because we can just iterate over them get the file directory, get the lock at the lock run the maintenance task unlock it and go to the next cash. Yeah, that makes sense. But my question is different. How to get that, how to get the list of cash entry. Well, and that's where I think that the cash entry is a derived a value derived from the list of remotes isn't it. So once it's derived from the list of remotes, we could either make the interface use. We could either use remotes, as it's doing right now right it's locking is all based on remotes for sure cash I think that's what you said is the locks here are cash entries are computed from a remote and the dollars interface with this through a remote. So if we go ahead. I have a way so can we do it like this country read the cash directly like cash directory, like Jenkins or get through cash directory, and then it, you know, read all the, you know, read all the directories present in it, and you know, split the folder, like the folder name. It's appended using get dot get dash and then some hash. Okay, so we get that hash and then add that hash into the hatch set. We could but how is that any better than just using I mean, yes we could we could the cash entry is the directory name. Right this cash entry is the name of that directory. So if we're willing to allow access to for willing for instance to allow the acquisition of a lock, based on cash entry. In addition to being based on remote. Yeah, that would work just fine because then we just use the cash entries. So if, if there were another, let's say there were another get cash lock method that instead of taking a string cash we could take a file. And when it takes a file the thing we pass is the directory, wouldn't that give the effect that you're describing and then, and you or any, any caller can can iterate over the list of, of directories in the caches folder. So those are the keys to be used now. That's, that's putting knowledge about the caches contents outside of this abstract get SCM source class, but I think I think that could work as well couldn't it. Wait, how are we putting that outside the knowledge of this class. Like, can you explain that but so my thought was, if we if if you're uncomfortable using the concept of cash remotes, this idea. We could also in we could instead of using cash remotes we could return a list of all the all the cash entries. That's basically the list of directory names in the caches folder, and then add a add some way to allow this method get cash lock based on cash entry to be accessed from outside the class. We can add a method and this class itself like I already added a method which gets all the, you know, detail. All the cash is present on this on the Jenkins controller. Okay. And you know you. So using that one, we get all the caches and then with that I think we can create a new method to pass the file. I think that that would work. And the thing that you're worried about, isn't that already possible for me if I have the significant Jenkins instance, and if I can access a folder called caches by calling a method from that instance, then I can essentially reverse engineer the list of cash entries right. Yes, yes, absolutely. Yes. Yeah, so so it's, it's, it's not that this is a security thing. I was just worried about an in cap and information in caps information hiding thing. But I think absolutely. If it's easier to access this thing as directories. You know, you're bound and pass the cash entry into this method say I'd like to lock based on cash entry. Yeah, now that's, that's a little complicated because they get cash lock method right. Well, actually it's not because it's exactly using a cash entry. Yeah, so we could just have a way of iterating over cash entries, return a list of cash entries and then Russia cash. It iterates over the cash entries from the from the maintenance object and says this cash entry, get the lock perform the maintenance then this one get the lock perform the maintenance. So crucially cash, are you okay with that idea I think using the cash entry a list of cash entries it looks great with me. Yeah, we can create a list of cash entries in this class itself. And then you know, iteration of the cash entries would be happening in the get maintenance. Yeah, that's what I was thinking is is this thing. Instead of having a set of strings. Like it's roughed in their cash remotes, it's just cash entries. Right, something like that. And, and that cash entries is the set of all all available cash entries on this thing and that could be generated generated at startup by reading the directory contents and then maintained based on accesses yeah why not. But I think, if we think about the choice between providing the list of remotes and list of entries, I believe, providing the list of remotes is what we should do because the user should not be concerned, the user of an abstract kid SCM should be concerned with the remote you are in cash entry is an internal system detail that it doesn't need to be concerned with. And I'm, I'm fine with that logic as well that that's that that would work just as well for me either in either case, we're creating a list, a set of something. And then the, the caller, the maintenance task uses that list of something and walks through the list, acquiring a lock for each entry in the list performing the maintenance tasks and requiring a lock performing the maintenance test. Either one is fine with me. I think you're right it could. It could be the thing that we store in this list in this set could be the remote, or it could be the cash entry. And I think you're right that remote is the one that's currently used as the external interface who should cash I think that's what you had told us as well right is remote is the external interface. So that but that just means store the remote. We have to read the remote value at a slightly different place in this file. Getting to the most I think would be a difficult task like because we'll be using the line plugin again. Right. Yeah, and that's why I don't object to declaring that there is a there is an abstract there is a concept here called a cash entry. And that concept is to be treated as opaque by the caller, you you receive a cash entry back as the maintenance task. And the cash entry you don't know what the meaning of the thing is you don't know that it's a directory, and we're not going to tell you that it's a directory, it's just a cash entry. And so in that sense, I think that's as that is as obfuscated or as as as effective information hiding almost as the remote URL. So what do you think of my logic does that sound fair that. Yes, I believe it does because if you think more about a cash entry and the remote name, both are interchangeable in some sense if you know what how the cash entry is being made. Anyone could go and see how it is being made that abstract data source. So those two definition essentially those two entities are saying, in terms of their value. And since abstracted SM source does provide an explicit method to get the cash entry based on the remote you are, then it is also willing to expose that concept to the user so I don't see a problem, providing a list of cash entries, instead of a single one based on the Okay, so then said Russia cash you've got, you've got me and Richard both who say using cash entries as a list is fine. That's great. Go for it. Thank you. Thanks for your patience here I apologize I'm getting a little weary here it's, it's getting late my time. Anything else we need to review before I go to sleep. I have a few more questions but I think it takes a lot of time so we can schedule a meet again, like, it's getting late for you. So, so if, if, if another meeting is later this week on a Saturday like we had it last day. So that will be that that may be just as every bit is daunting. How about we try to get through your questions here and see if we can, we can resolve them before I get to two out of it. And, and then, then, if we still need to meet over the weekend we can. I think I okay I'll not take much time I'll ask like the most important ones, like about task listener like what exactly like the get client plug in takes in the task listener. Okay. I, is a task listener similar to you know reading on writing a log file. It is, but it's a log file it's a log in, in a context of a specific activity. So, so here if we look at the Java doc. Okay, so, so a task listener is a way of recording things that are going on and taking expected to take some time. And those things include a build right or an SCM checkout or the launch of an agent. And so what this is is this is a narrow scoped log for a specific activity. How would I be using this like how would it be. Well so a build log for instance is is a specific task listener. And so when, when a build is running inside a Jenkins job, the way the get client records the progress of its operations is by writing to a task listener. You might, you might choose to use a task listener for each of the maintenance tasks. And that way then you have a facility if you need it to display the log of maintenance operations to the user. Okay. So that would be helpful in the second phase of the coding PDA, where I have to display. Right. Because maintenance operations seem like they fit really well with the description here they are lengthy operations that has a chance of failure. There could be a concurrency problem there could be a data corruption problem in a cache. And so, so we'll want and so I think a task listener is a good choice of a way to record what the how the how the maintenance task is proceeding. All other questions I think can be answered are another time that they are all like not related to what I would be doing this week. So I think that's, that's fine. Okay, all right. Thanks for your cash. Thanks, Rishabh anything else we need to discuss then. Thank you for my sake. All right, so I am going to go get some sleep, the recording won't be posted until at least 12 hours from now because I, I, I won't even look at it for at least eight or 10. All right, thanks everybody. See stop the recording.