-
Notifications
You must be signed in to change notification settings - Fork 32
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
Enable server use as a library #11
Conversation
7f11a17
to
e03b010
Compare
pkg/config/config.go
Outdated
@@ -20,21 +20,24 @@ type Module struct { | |||
ACL []string `toml:"acl"` | |||
} | |||
|
|||
func NewModule(name string, path string, acl []string) Module { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is needed for the client code that uses this as a library.
Since this is somewhat core concept of the serving part, I was left wondering if the module type should belong to root level package in this repo, or actually in rsyncd package, but I don't know. I wrote my question here mainly to flag it for you if you have any thoughts. Here is probably fine too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The generic name of this package brought a problem the very first time I imported into my concrete project. I had to rename the import:
rsyncdconfig "github.com/gokrazy/rsync/pkg/config"
because my package already had declared config
identifier. Should the package be renamed to rsyncdconfig
, or do you think having the user rename the import is the better way?
pkg/config/config.go
Outdated
cfg.ModuleMap = make(map[string]Module) | ||
for _, m := range cfg.Modules { | ||
cfg.ModuleMap[m.Name] = m | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One nice place of improvement is here: no need to compute the module map. One less place where data can be out of sync (think somebody later changes the Modules
fields but does not realize ModuleMap
is actually the authoritative one.
Same for ModuleMap key (being the name). If someone changes the Name
in the Module
structure, they've to remember to change the map key too.
.github/workflows/main.yml
Outdated
@@ -50,7 +50,7 @@ jobs: | |||
|
|||
- name: run tests (macos) | |||
if: matrix.os == 'macos-latest' | |||
run: go test -v ./internal/... && go test -c && sudo ./rsync.test -test.v | |||
run: go test -v ./pkg/... && go test -c && sudo ./rsync.test -test.v |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
GitHub actions workflow now pass in my fork
Whether this is an appropriate fix depends on whether the blanket internal -> pkg rename is ok for now
Thanks for sending this!
Actually, it might be easiest to file a new issue and then send small individual PRs for each logical change, with each PR referencing the issue so that we have a good paper trail :) That way, we can merge things piece by piece instead of having to get everything ready at once.
Thanks, the log message changes are fine. These would be good to send as a separate PR, for example.
I don’t like having But, as you already wrote, this blanket change is probably going too far. I think we should carefully consider each type we export, even if it’s more work.
Sounds good! Can you send this as a separate PR, too, please?
Sounds good as well!
Ah, this is quite a confusing situation when talking about rsync. The rsync protocol can run either in “sender” or in “receiver” mode. However, both client and server can fulfill either role! It depends on the flags with which they were started. For example, you could have a client connect to a server and then act as a sender to upload a backup of your PC (client) to your network storage (server). Or, you could have a client connect to a server and then act as a receiver to download a Linux distribution’s package repository. I agree that currently, the terminology used in the repository is not entirely clear. But, the desired state is that the terms sender, receiver, client and server are all used, and refer to different, orthogonal concepts (rsync protocol role vs. network connection role). The maincmd package fulfills the same role as the upstream rsync implementation: one binary which can run in all the different modes. |
7c3829a
to
57c7fcc
Compare
Thanks for the great feedback! Thanks for explaining the rsync sender/receiver/client/server difficulty. Yeah that was new info to me, I stll need to digest it a bit lol 😄 I've extracted different logical changes to own PRs and created an issue to serve as the paper trail for the high-level work. Still TODO here: internal -> pkg rename. In my project's I've been following the pkg/ approach. I however appreciate the fact that this is not my project. :) How should we continue with the packages that need to be public? rsyncd & config have been identified. Would this work:
? One thing I'm hesitant about the naming, since |
Thanks for sending the PRs!
You’re welcome! Maybe you could add a package-level comment that explains this while you’re at it? Otherwise, I can add one later.
I don’t have strong opinions on this, but found the goal of keeping your domain types in the top-level attractive. E.g. I found golang-standards/project-layout#10 to be a good read in case you haven’t seen that yet.
Yes
Yeah, let’s rename it to |
57c7fcc
to
1642435
Compare
On pkg/
I haven't read that yet, thank you! 👍 Many good points for and against. My biggest "cmd/* internal/* pkg/* are good" observation is that it very clearly separates Go code from "other" files, such as documentation, "misc files" (be it project logo etc.) but most importantly, separate subsystems written in other languages. I have repos where I have TypeScript-based frontend for a Go backend, so I very much like keeping the things in separate hierarchies. :) I appreciate that Go-only projects don't need this, but I prefer consistency (Go-only projects don't look different to Go + frontend language projects). Of course one could have different repositories for these subsystems, but monorepo vs. multi-repo is a different topic and not without obvious caveats: added complexity, atomic commits not possible (or as easy) as in a monorepo etc.. But I'm going off-topic now.. It's good to get different perspective! I need to continue evaluating my stance on pkg/ :) Open questionsI now moved Now looking at it, I'm not happy with it. Thoughts:
|
I clearly have no idea what I'm doing with Git. I got merge conflicts where I didn't think there should be, and had to do an additional merge. I can clean up the history later when this looks ready for merging. Perhaps best to just look at overall changes, not the noisy commits for now.. |
For this, I have come to prefer directories whose name starts with an
Yeah, I think making it part of the
Have you tried rebasing your changes? Alternatively just copy the files, throw away history and commit fresh :) |
3daa1f1
to
edb6e09
Compare
Listeners []Listener `toml:"listener"` | ||
Modules []Module `toml:"module"` | ||
Listeners []Listener `toml:"listener"` | ||
Modules []rsyncd.Module `toml:"module"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As per our discussion, no need to expose this config package if Module
is defined by rsyncd
package itself.
Also related: we discussed earlier renaming config -> rsyncdconfig. I reverted the rename and left it out from this PR, since the package is not needed as public.
If you want, I can send another PR renaming internal/config
-> internal/rsyncdconfig
. But it wasn't necessary here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you have time for the internal/config
→ internal/rsyncdconfig
change as well, I’ll gladly take that as a separate pull request later :)
rsyncd/rsyncd.go
Outdated
ACL []string `toml:"acl"` | ||
} | ||
|
||
func NewServer(modules ...Module) (*Server, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can now fail due to added validation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I commented about this in earlier comment (you wanted to remove NewModule() for extensibility, I think that makes validation more important)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BTW I'm not super sold on ...Module
instead of []Module
, as that rules out future option-arguments.
The original rationale was that some rsyncd library callers may have hardcoded modules so it just looks nicer when you don't need a slice.
(Maybe this is non-issue if you don't have issues breaking backwards compat before v1 release.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fair point. Let’s use []Module
here, also because a zero-module server is not generally useful, so having rsyncd.NewServer()
fail at compile-time is actually desired.
Sorry it took me so long to get back to this. This has taken more time than I had allocated (not your fault!), so I had to find some more free time :) |
(The PR message's example user code is up-to-date now) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is looking good! Added a few more comments but I think we can merge this soon :)
rsyncd/rsyncd.go
Outdated
return errors.New("module has no name") | ||
} | ||
if mod.Path == "" { | ||
return fmt.Errorf("module '%s' has empty path", mod.Name) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use %q instead of '%s' please
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lol you just taught me what %q means, never used or knew of it before 😆
rsyncd/rsyncd.go
Outdated
ACL []string `toml:"acl"` | ||
} | ||
|
||
func NewServer(modules ...Module) (*Server, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fair point. Let’s use []Module
here, also because a zero-module server is not generally useful, so having rsyncd.NewServer()
fail at compile-time is actually desired.
Listeners []Listener `toml:"listener"` | ||
Modules []Module `toml:"module"` | ||
Listeners []Listener `toml:"listener"` | ||
Modules []rsyncd.Module `toml:"module"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you have time for the internal/config
→ internal/rsyncdconfig
change as well, I’ll gladly take that as a separate pull request later :)
edb6e09
to
b9aad4b
Compare
I submitted the fixes! For some reason I can't respond to all of your comments, so here goes:
Yeah I will send it after this has been merged!
Sidenote: you can also use |
Thanks a lot for contributing this! |
Meta
Issue: #12
Rebase of older PR: #3 (opened new PR because I wanted to use a branch in my fork instead of main, and I don't think you can change branch in an existing PR)
Example user application
This works:
Notes on this PR
Logger *log.Logger
field inrsyncd.Server
whichNewServer()
maybe sets tolog.Default()
by default (preserving the current behaviour) or has to be given explicitly (have not thought of this yet), so user can give discarding logger to make the library quiet. But that could be a new PR, there is quite a bunch of stuff here already.General notes
With my fresh eyes on this codebase, a few notes: