Skip to content
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

GH-8691: Support age FTP, SMB over time filters #8725

Closed
wants to merge 10 commits into from

Conversation

AdamaSorho
Copy link
Contributor

fixes #8691

Add LastModifiedFTPFileListFilter and LastModifiedSmbFileListFilter respectively for FTP and SMB to enhance available files filtering based on a last-modified strategy.

@AdamaSorho
Copy link
Contributor Author

I ran the tests before starting to work on the issue, but I am getting an error for sftp. So, I did not touch this module. Let me know if I must configure something to pass this test. I will add age support filtering to sftp module once I pass the tests.

See screenshot below:
SFTP test error

@artembilan
Copy link
Member

Thank you for reporting that @AdamaSorho !

Please, consider to add testRuntimeOnly 'net.i2p.crypto:eddsa:0.3.0' into spring-integration-sftp module. See build.gradle.
As part of your PR is OK. Turned out you are not only one who faced this problem for non-default known_hosts file.

Also: please, stop posting screenshots for stacktraces: it would much easier for me to copy/paste info for search 😄

@AdamaSorho
Copy link
Contributor Author

Understood, sorry about that.

The tests passed now for sftp module. Could you tell me why we need net.i2p.crypto:eddsa:0.3.0? I don't know understand 🙈

Thank you

@artembilan
Copy link
Member

We need that library to be able to parse that Ed25519 encrypted key in your known_hosts file: https://github.com/str4d/ed25519-java

@AdamaSorho
Copy link
Contributor Author

Ok I see. Thank you

*
* @since 6.2
*/
public class LastModifiedFTPFileListFilter implements DiscardAwareFileListFilter<FTPFile> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'd prefer to name this as FtpLastModifiedFileListFilter

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only this should be renamed or the other classes too?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right. Others, too. Just follow same pattern for consistency.


private static final long ONE_SECOND = 1000;
private static final long DEFAULT_AGE = 60;
private volatile long age = DEFAULT_AGE;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Every member in the class must be surrounded with blank lines (including the last method in class before that closing }): much easier to read the code.
No need to have this as a volatile: I don't believe in properties changing at runtime where you cannot predict which one is going to be used right after that.

We also need to see if better to save this value as a Duration.

That FTPFile exposes an API like this:

    /**
     * Gets the file timestamp. This usually the last modification time.
     *
     * @return A Calendar instance representing the file timestamp.
     * @since 3.9.0
     */
    public Instant getTimestampInstant() {

which is nice to work with Duration.

*/
@SpringJUnitConfig
@DirtiesContext
public class LastModifiedFTPFileListFilterTests extends FtpTestSupport {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we really need the real Spring configuration and FTP server to just test a logic of last modified filter?

}

private boolean fileIsAged(SftpClient.DirEntry file, long now) {
return file.getAttributes().getModifyTime().to(TimeUnit.SECONDS) + this.age <= now;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here about Duration and FileTime.toInstant()

*/
@SpringJUnitConfig
@DirtiesContext
public class LastModifiedSftpFileListFilterTests extends SftpTestSupport {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here about unreasonable overhead with Spring config and real SFTP server.

}

private boolean fileIsAged(SmbFile file, long now) {
return file.getLastModified() / ONE_SECOND + this.age <= now;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This SMB API does not provide an Instant representation, so, we have to stick with millis.
However those blank lines around members an removal of volatile are still valid concerns.

*/
@SpringJUnitConfig
@DirtiesContext
public class LastModifiedSmbFileListFilterTests extends SmbTestSupport {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And this one is more drastic than others: it starts a Docker container for Samba server.
Therefore I'd prefer to have all these new tests against mocks and fully in-memory.

Copy link
Member

@artembilan artembilan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is very close to the merge.

Now, let's consider to mentioned these new filters in the respective FTP, SFTP and SMB chapters of the docs.
The change could make it into the ftp/inbound.adoc, sftp/inbound.adoc, and smb.adoc, respectively.

The whats-new.adoc also must have a new simple section like === Remote Files Support Changes and mention all new filter there.

Thank you!

* @param age the age in seconds.
* @param unit the timeUnit.
*/
public void setAge(long age, TimeUnit unit) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we need a TimeUnit-based API since we have a Duration-one. It really covers any possible time units.

@Test
public void testAge() {
FtpLastModifiedFileListFilter filter = new FtpLastModifiedFileListFilter();
filter.setAge(60, TimeUnit.SECONDS);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need to set this value if it is exactly what we have by default?

@@ -0,0 +1,147 @@
/*
* Copyright 2015-2023 the original author or authors.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This class was really created in the 2023. Therefore copyright is just for the current year.

@@ -0,0 +1,143 @@
/*
* Copyright 2013-2023 the original author or authors.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DITTO

* @param age the age in seconds.
* @param unit the timeUnit.
*/
public void setAge(long age, TimeUnit unit) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DITTO

Copy link
Member

@artembilan artembilan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like something is wrong with your Git workflow.

  1. Switch to main
  2. Perform git pull upstream main
  3. Switch back to your branch
  4. Perform git rebase main
  5. git push origin -f

Otherwise your PR contains changes you didn't do. Plus it suggests them as new changes somehow...

Copy link
Member

@artembilan artembilan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK. Just one nit-pick.
Will take care about that on merge.

Forgot to mention: when we force push to the PR, GitHub doesn't notify us about changes.
So, consider in the future to leave some comment that it ready for review.

Thanks

* @param age the age in seconds.
* @param unit the timeUnit.
*/
public void setAge(long age, TimeUnit unit) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this one is still has to be remove: the Duration does the trick for us anyway.

Copy link
Member

@artembilan artembilan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK. After looking into this closely, I suggest this evolution.

How about extracting an AstractLastModifiedFileListFilter<F> with all the common logic and only leave something like abstract Instant getLastModified(F remoteFile); for the implementors?
I believe this way even that existing LastModifiedFileListFilter could benefit from new super class.

Yes, some of the implementors would need to use Instant.ofEpochSecond() to convert their long to expected format by super class.

public FtpLastModifiedFileListFilter ftpLastModifiedFileListFilter() {
FtpLastModifiedFileListFilter filter = new FtpLastModifiedFileListFilter();

filter.setAge(Duration.ofSeconds(180));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have ctor for this. Therefore this sample would end up with a single line.
More over I think we don't this examples at all: the API of the class is pretty straightforward and there is a good Javadoc.
We may say though, please, look into its Javadoc for more info.

@AdamaSorho
Copy link
Contributor Author

Yeah, that will be perfect!


protected abstract Instant getLastModified(F remoteFile);

protected Duration getCurrentAge() {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added this method because we have a long getAge() in LastModifiedFileListFilter for backward compatibility.

I think we should deprecate long getAge().

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, let's deprecate that one with no replacement.
This protected one probably still makes sense, but let's call it getAgeDuration()!

Copy link
Member

@artembilan artembilan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks very cool!
Just a couple minor comments.

You may not be agreed with me on some of them, so just comment with your arguments.
Otherwise I believe it can be merged after those fixes.


protected abstract Instant getLastModified(F remoteFile);

protected Duration getCurrentAge() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, let's deprecate that one with no replacement.
This protected one probably still makes sense, but let's call it getAgeDuration()!

*/
public class SmbLastModifiedFileListFilter extends AbstractLastModifiedFileListFilter<SmbFile> {

private static final long ONE_SECOND = 1000;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this can go to super class as protected constant. Even if it is not used over there, it is still convenient for its implementors and we won't duplicate ourselves.

Copy link
Member

@artembilan artembilan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pulling locally for the final review, clean up and merge...

@artembilan
Copy link
Member

Merged as 73ed3ee after some clean up.

Thank you again for contributions!

@artembilan artembilan closed this Sep 14, 2023
@AdamaSorho AdamaSorho deleted the GH-8691 branch September 14, 2023 17:12
@AdamaSorho
Copy link
Contributor Author

Thank you!

Don't hesitate to ping me on any issue at anytime.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support age (s/ftp) and size over time filters (both file and s/ftp)
2 participants