-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[WEP] Service tooling proposal #3496
base: v3-alpha
Are you sure you want to change the base?
Conversation
Deploying wails with Cloudflare Pages
|
First of all thank you for your work on this and sorry for the very late feedback. It is true, as you wrote in the proposal, that people can manage services by hand without too much effort. Nonetheless, I think this contribution fits very well wails' mentality of providing ergonomic, moderately opinionated development tools on top of the go distribution, and it is definitely going to play a part, however small, in making the developer experience smoother and simpler. I would like to object to the currently proposed code layout, and suggest an alternative. The main problem IMO is that it does not fit very well the layout of generated JS code, and it is going to introduce friction for the developers on the frontend side. A secondary problem is that I don't think having a per-service go.mod file makes sense for application-level services, which are most probably going to import internal subpackages of the application module, and are probably never going to be reused. Regarding the main problem, the binding generator currently outputs:
Service files can be imported with the usual syntax import * as ServiceName from "<package>/<servicename>.js" whereas index files are designed to facilitate imports like this import {ServiceName1, ServiceName2} from "<package>"; Having one folder per service is gonna make indexes redundant and practically useless, as well as complicate JS imports, which need to be typed by hand. The former pattern is going to become: import * as ServiceName from "<package>/<servicename>/<servicename>.js" The latter will look like this: import {ServiceName1} "<package>/<servicename1>";
import {ServiceName2} "<package>/<servicename2>"; Not nice... I understand that having per-service folders was meant to facilitate method handling, and I am gonna propose a couple alternative solutions below. Regarding the secondary problem, I explained my reasons above. I'd just like to add this: I remember reading around the internet that having nested go.mod files should always be avoided, except for versioning purposes. I always try to abide by this rule, but maybe it was just someone's personal opinion? Aren't there any drawbacks to this? On to the alternatives. I'd like to propose the following layout for applications:
For reusable, non application-specific services, I propose adding a new plugin template to the init command that would result in the following layout:
The service tool would use the former layout if the current package is main, the latter if it is non-main. This logic has the added benefit of making the service tool work seamlessly in the services folder, as well as in any other subpackage that might want to export its own services. The A service file type ServiceName struct { /* ... */ }
func (s *ServiceName) InitService() { /* ... */ }
func (s *ServiceName) ShutdownService() { /* ... */ } as well as any user-defined methods. The func Services() application.Service {
return application.CombineServices(
application.NewService(&ServiceName1{}),
application.NewService(&ServiceName2{}),
)
} The name Then application templates would be amended to include the following default configuration: import "<module path>/services"
// ...
func main() {
// ...
application.New(application.Options{
// ...
Bind: []application.Service{
services.Services(),
},
// ...
})
// ...
}
Let me explain the rationale behind this approach:
Two problems still have to be handled:
Problem 1 can be easily solved by parsing the package, then editing the Go AST and printing it back instead of manipulating source code directly. The only constraint being that the Problem 2 can be solved in the same way, but I was actually thinking that maybe method handling could be omitted entirely. Service methods are not the same as routes/actions in a web framework: they are just plain simple Go methods, with zero boilerplate. I don't see this feature being used much, and I feel like it would be a bit overkill. The only case where we'd still need to edit methods would be service renaming and removal, and it can be easily done with the type-checker + AST editing. I am of course available for help or discussion in implementing AST/type manipulation. In this regard, I was having a look at things to understand how hard it would be and I found this interesting lib: https://pkg.go.dev/github.com/dave/dst |
Thanks @fbbdev for the insightful feedback 🙏 I'm making services for myselfThis is almost certainly the default use case and the one we should consider the most. In this scenario, there is no need for I'm making a sharable serviceThis is where someone has written a service and would like to share it. Sharing should absolutely be done via Go modules. So then the question is, how do we get from a local service to a shareable one? Perhaps it's just adding a The only issue with composing multiple services into the same folder is that each 3rd party library you pull in may have different package names (they might not all be We should also be clear on terms 😅 For me a service is discrete & shareable code that can be given to the I would be very wary of manipulating source code or copying code from 3rd party packages to local directories as, honestly, I think it's going to be very hard with lots of opportunities to go wrong. The ideal scenario is where someone uses Again, thanks for taking the time to provide feedback. What a great community we have! 🚀 |
I'm not sure if I understand the concern on this, it would essentially just be acting as if created a package for something and generate as such. I was under the impression this move was mostly going to be handled with the golangs build system for instance I can There would be a concern of imports here being fairly lengthy on the frontend but could that be solved with the plugin.yml? maybe parser checks if there's a "package" field that standard should be similar to neovim package managers for example |
Description
This proposal outlines new CLI functionality for the new "Services" concept in v3, which can be user to create new services in a standard way. It offers a foundation for future service management, such as installing 3rd party services.
I'm willing to implement this myself.