<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Anton</title>
    <description>The latest articles on DEV Community by Anton (@sky003).</description>
    <link>https://dev.to/sky003</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1198140%2Fa2dda1a4-b95d-4c49-bed3-a358c78e79d4.png</url>
      <title>DEV Community: Anton</title>
      <link>https://dev.to/sky003</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sky003"/>
    <language>en</language>
    <item>
      <title>Integrate any command into your file-processing pipeline</title>
      <dc:creator>Anton</dc:creator>
      <pubDate>Mon, 27 Nov 2023 13:36:58 +0000</pubDate>
      <link>https://dev.to/sky003/integrate-any-command-into-your-file-processing-pipeline-3jbh</link>
      <guid>https://dev.to/sky003/integrate-any-command-into-your-file-processing-pipeline-3jbh</guid>
      <description>&lt;p&gt;Here I want to show you how to integrate an arbitrary command that performs certain manipulations on your file into the file-processing pipeline. A file-processing pipeline we are going to work with is called Capyfile. It’s free, open-source, and written in Golang. If you want to familiarize yourself with the Capyfile, you can check an article called &lt;a href="https://dev.to/sky003/do-whatever-you-want-with-your-files-and-do-it-quickly-4od2"&gt;Do whatever you want with your files, and do it quickly&lt;/a&gt;. Or just check its repository on &lt;a href="https://github.com/capyfile/capyfile"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Capyfile goes with the built-in file-processing operations that allow you to retrieve, validate, modify, and store your files. In addition to these, I decided to add one more operation that allows you to run external commands. This can be pretty much any command that works with the files, such as ffmpeg, exiftool, zip, wget, aws cli, etc. Let me show you how on a few examples.&lt;/p&gt;

&lt;h2&gt;
  
  
  Transcode video with ffmpeg
&lt;/h2&gt;

&lt;p&gt;Let’s say you have a directory with a bunch of avi video files and you want to transcode these to mp4. Here’s your file-processing pipeline configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;---
version: '1.1'
name: videos
processors:
  - name: transcode_avi_to_mp4
    operations:
      - name: filesystem_input_read
        cleanupPolicy: keep_files
        params:
          target:
            sourceType: env_var
            source: INPUT_READ_TARGET
      - name: file_type_validate
        params:
          allowedMimeTypes:
            sourceType: value
            source:
              - video/x-msvideo
      - name: command_exec
        cleanupPolicy: remove_files
        params:
          commandName:
            sourceType: value
            source: ffmpeg
          commandArgs:
            sourceType: value
            source: [
              "-i", "{{.AbsolutePath}}",
              "-c:v", "copy",
              "-c:a", "copy",
              "/tmp/{{.Basename}}.mp4",
            ]
          outputFileDestination:
            sourceType: value
            source: /tmp/{{.Basename}}.mp4
      - name: filesystem_input_write
        params:
          destination:
            sourceType: env_var
            source: INPUT_WRITE_DESTINATION
          useOriginalFilename:
            sourceType: value
            source: true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can run it with capycmd command line app:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ INPUT_READ_TARGET=/home/user/Videos/* \ 
  INPUT_WRITE_DESTINATION=/home/user/Videos/transcoded \ 
  capycmd -f service-definition.yml videos:transcode_avi_to_mp4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Compress and archive old logs
&lt;/h2&gt;

&lt;p&gt;If you saw the repository, you may remember the log archiver example. What was missing there? Probably compression. And now we can add it this way:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;---
version: '1.1'
name: logs
processors:
  - name: archive
    operations:
      - name: filesystem_input_read
        cleanupPolicy: keep_files
        params:
          target:
            sourceType: env_var
            source: INPUT_READ_TARGET
      - name: file_time_validate
        params:
          maxMtime:
            sourceType: env_var
            source: MAX_LOG_FILE_TIME_RFC3339
      - name: command_exec
        cleanupPolicy: remove_files
        params:
          commandName:
            sourceType: value
            source: gzip
          commandArgs:
            sourceType: value
            source: ["{{.AbsolutePath}}"]
          outputFileDestination:
            sourceType: value
            source: "{{.AbsolutePath}}.gz"
      - name: command_exec
        params:
          commandName:
            sourceType: value
            source: aws
          commandArgs:
            sourceType: value
            source: [
              "s3",
              "cp", "{{.AbsolutePath}}",
              "s3://my_logs_bucket/{{.Filename}}",
            ]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ INPUT_READ_TARGET=/var/log/rotated-logs* \
  MAX_LOG_FILE_TIME_RFC3339=$(date -d "30 days ago" -u +"%Y-%m-%dT%H:%M:%SZ") \
  capycmd -f service-definition.yml logs:archive
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Download the archive and process individual files in it
&lt;/h2&gt;

&lt;p&gt;So you have an archive and you want to unpack it and process each file in it. For example, let’s download the archive of images and do some transformations for all images in the archive:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;---
version: '1.1'
name: web_images
processors:
  - name: unpack
    operations:
      - name: command_exec
        params:
          commandName:
            sourceType: value
            source: bash
          commandArgs:
            sourceType: value
            source:
              - -c
              - &amp;gt;
                wget -O /tmp/images.zip https://example.com/images.zip;
                mkdir -p /tmp/web_images; 
                unzip /tmp/images.zip -d /tmp/web_images
      - name: filesystem_input_read
        cleanupPolicy: remove_files
        params:
          target:
            sourceType: value
            source: "/tmp/web_images/*"
      - name: file_type_validate
        params:
          allowedMimeTypes:
            sourceType: value
            source:
              - image/jpeg
              - image/png
              - image/heif
      - name: image_convert
        cleanupPolicy: remove_files
        params:
          toMimeType:
            sourceType: value
            source: image/jpeg
          quality:
            sourceType: value
            source: high
      - name: filesystem_input_write
        params:
          destination:
            sourceType: env_var
            source: INPUT_WRITE_DESTINATION
          useOriginalFilename:
            sourceType: value
            source: true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And as usual, run it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ INPUT_WRITE_DESTINATION=/home/user/Pictures/web_images \
  capycmd -f service-definition.yml web_images:unpack
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  In the end
&lt;/h2&gt;

&lt;p&gt;The ability to seamlessly integrate and execute arbitrary commands exponentially increases the number of use cases that Capyfile can cover. So feel free to try it out and share your feedback or any ideas that you have.&lt;/p&gt;

</description>
      <category>go</category>
      <category>tooling</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Do whatever you want with your files, and do it quickly</title>
      <dc:creator>Anton</dc:creator>
      <pubDate>Mon, 13 Nov 2023 14:44:58 +0000</pubDate>
      <link>https://dev.to/sky003/do-whatever-you-want-with-your-files-and-do-it-quickly-4od2</link>
      <guid>https://dev.to/sky003/do-whatever-you-want-with-your-files-and-do-it-quickly-4od2</guid>
      <description>&lt;p&gt;File processing is a very common task in software development and data management. During my engineering career, I’ve been mostly building software that works on the servers. And if we are talking about the files, let me tell you a little about what I saw.&lt;/p&gt;

&lt;p&gt;There was so much boilerplate code that checks the uploaded files and proxies them to S3 storage. The same is true about media transforming/transcoding that you do yourself. The first you do is find some lib that wraps ImageMagick, Vips, or FFmpeg. And then you write some code that supplies the lib with the parameters and the processable input. Another type of task you may see is finding some files, doing some basic analysis, and based on its results moving/removing/archiving the files. For some of such tasks, there are one-liners that you paste into your terminal, there may be specific tools/utils. If not, you probably end up writing a bash/python script that does what you need.&lt;/p&gt;

&lt;p&gt;This is true that in some cases a custom solution is required. You may want the highest level of customization. It can be a business requirement or compliance. Or you just want to write and support it yourself which is sometimes totally fine too. But what if none of the above is your case?&lt;/p&gt;

&lt;p&gt;If what you want is a set of operations that you can run your files through, perhaps, there’s a solution for you. It’s open source, and I recently decided that it’s okay to push the v1.0.0 tag into its repository. So let me show what it is I’m working on.&lt;/p&gt;

&lt;h2&gt;
  
  
  File processing pipeline
&lt;/h2&gt;

&lt;p&gt;I called it &lt;strong&gt;Capyfile&lt;/strong&gt;. This is a file-processing pipeline that you can construct yourself. A nice bonus is that it can process the files concurrently. Its source code is available on GitHub:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/capyfile/capyfile"&gt;https://github.com/capyfile/capyfile&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The overall architecture is quite simple. To start working with it you should know about two things.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pipeline configuration file
&lt;/h3&gt;

&lt;p&gt;First, you need a configuration file that defines your pipelines. The main purpose of this file is to group your pipelines and configure the operations that belong to them.&lt;/p&gt;

&lt;p&gt;Besides the operations, there are two more entities that the configuration file consists of. Their main purpose for now is to group the pipelines. Service entity is used to group the processors. Processor entity is used to group the operations. So you can refer to your pipeline with a composite ID that is &lt;code&gt;{Service}:{Processor}&lt;/code&gt; or &lt;code&gt;{Service}/{Processor}&lt;/code&gt;. How you name these is up to you. For example, you want a config file for the pipeline that you use for image processing. It can be those: &lt;code&gt;images:compress&lt;/code&gt;, &lt;code&gt;images:transform&lt;/code&gt;, &lt;code&gt;images:archive&lt;/code&gt;, etc.&lt;/p&gt;

&lt;p&gt;There are a few things that you want to know about the operations. One pipeline can consist of many operations and you can put them in any order that makes sense to you. Here's the list of operations available at this moment:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;http_multipart_form_input_read&lt;/code&gt; - read the files from the HTTP request body as &lt;code&gt;multipart/form-data&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;http_octet_stream_input_read&lt;/code&gt; - read the files from the HTTP request body as &lt;code&gt;application/octet-stream&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;filesystem_input_read&lt;/code&gt; - read the files from the filesystem&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;filesystem_input_write&lt;/code&gt; - write the files to the filesystem&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;filesystem_input_remove&lt;/code&gt; - remove the files from the filesystem&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;file_size_validate&lt;/code&gt; - check file size&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;file_type_validate&lt;/code&gt; - check file MIME type&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;file_time_validate&lt;/code&gt; - check file time stat&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;axiftool_metadata_cleanup&lt;/code&gt; - clear file metadata if possible (require exiftool)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;image_convert&lt;/code&gt; - convert image to another format (require libvips)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;s3_upload&lt;/code&gt; - upload file to S3-compatible storage &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Also, every operation has such thing as a file target policy. It defines what files the operation should process. The &lt;code&gt;targetFiles&lt;/code&gt; parameter can have those values:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;without_errors&lt;/code&gt; (default) - all files that are passed to the operation except files that have errors&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;with_errors&lt;/code&gt; - all files that are passed to the operation that have errors&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;all&lt;/code&gt; - all files that are passed to the operation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And, of course, the operations must be configured. Configuration values for the operations can be retrieved from the following sources:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;value&lt;/code&gt; - parameter value will be retrieved directly from the configuration file&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;env_var&lt;/code&gt; - parameter value will be retrieved from the environment variable&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;secret&lt;/code&gt; - parameter value will be retrieved from the secret (docker secret)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;file&lt;/code&gt; - parameter value will be retrieved from the file&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;http_get&lt;/code&gt; - parameter value will be retrieved from the HTTP GET parameter&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;http_post&lt;/code&gt; - parameter value will be retrieved from the HTTP POST parameter&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;http_header&lt;/code&gt; - parameter value will be retrieved from the HTTP header&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;etcd&lt;/code&gt; - parameter value will be retrieved from the etcd key-value store&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now when you know all these, you are ready to write your own configuration file. So let's write a couple configuration files. The format that it accepts right now is JSON and YAML.&lt;/p&gt;

&lt;h4&gt;
  
  
  Avatar upload example
&lt;/h4&gt;

&lt;p&gt;Let's say you are building a messenger and want functionality that allows your users to upload their avatar photos. Here's what the configuration file for your pipeline may look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;---
version: '1.1'
name: avatars
processors:
- name: upload
  operations:
  - name: http_multipart_form_data_input_read
  - name: file_size_validate
    params:
      maxFileSize:
        sourceType: value
        source: 10485760
  - name: file_type_validate
    params:
      allowedMimeTypes:
        sourceType: value
        source:
        - image/jpeg
        - image/png
        - image/heif
  - name: image_convert
    params:
      toMimeType:
        sourceType: value
        source: image/jpeg
      quality:
        sourceType: value
        source: high
  - name: exiftool_metadata_cleanup
  - name: s3_upload
    params:
      accessKeyId:
        sourceType: secret
        source: aws_access_key_id
      secretAccessKey:
        sourceType: secret
        source: aws_secret_access_key
      endpoint:
        sourceType: etcd
        source: "/services/messenger/aws_endpoint"
      region:
        sourceType: etcd
        source: "/services/messenger/aws_region"
      bucket:
        sourceType: env_var
        source: AWS_AVATARS_BUCKET
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can see how this pipeline processes the files step by step:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Retrieves the input from the HTTP request&lt;/li&gt;
&lt;li&gt;Ensures that the file size is less than 10MB &lt;/li&gt;
&lt;li&gt;Ensures that the file format is either png, jpg, or heif&lt;/li&gt;
&lt;li&gt;If necessary, converts the image to jpg&lt;/li&gt;
&lt;li&gt;Strips the image metadata&lt;/li&gt;
&lt;li&gt;Uploads the image to S3 storage&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Log archive example
&lt;/h4&gt;

&lt;p&gt;Let's say you have a bunch of log files and you want to achieve the ones that are older than 1 month. Here's the configuration file you may use for this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;---
version: '1.1'
name: logs
processors:
- name: archive
  operations:
  - name: filesystem_input_read
    params:
      target:
        sourceType: value
        source: "/var/log/rotated-logs/*"
  - name: file_time_validate
    params:
      maxMtime:
        sourceType: env_var
        source: MAX_LOG_FILE_AGE_RFC3339
  - name: s3_upload
    targetFiles: without_errors
    params:
      accessKeyId:
        sourceType: secret
        source: aws_access_key_id
      secretAccessKey:
        sourceType: secret
        source: aws_secret_access_key
      endpoint:
        sourceType: value
        source: s3.amazonaws.com
      region:
        sourceType: value
        source: us-east-1
      bucket:
        sourceType: env_var
        source: AWS_LOGS_BUCKET
  - name: filesystem_input_remove
    targetFiles: without_errors
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From the config, you can see what it does:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Reads the log files from the filesystem&lt;/li&gt;
&lt;li&gt;Checks max file mtime&lt;/li&gt;
&lt;li&gt;Uploads the files where mtime is older than 1 month ago to S3 storage&lt;/li&gt;
&lt;li&gt;Removes the files where mtime is older than 1 month ago&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Pipeline runner
&lt;/h3&gt;

&lt;p&gt;Now when we know how to configure the pipeline, we want to run it, right? Here you have two options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;via &lt;code&gt;capycmd&lt;/code&gt; command line application&lt;/li&gt;
&lt;li&gt;via &lt;code&gt;capysvr&lt;/code&gt; http server&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Avatar upload example
&lt;/h4&gt;

&lt;p&gt;Remember that avatar upload example? You probably already see that capysvr is the way to go here. So let's run it.&lt;/p&gt;

&lt;p&gt;The file called &lt;code&gt;service-definition.yml&lt;/code&gt; contains our pipeline configuration. And we can use the capysvr Docker image to run it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker run \
    --name capyfile_server \
    --mount type=bind,source=./service-definition.yml,target=/etc/capyfile/service-definition.yml \
    --env CAPYFILE_SERVICE_DEFINITION_FILE=/etc/capyfile/service-definition.yml \
    --env AWS_AVATARS_BUCKET=avatars \
    --secret aws_access_key_id \
    --secret aws_secret_access_key \
    -p 8024:80 \
    capyfile/capysvr:latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And if you want to load parameters from etcd, you can provide the etcd connection parameters via environment variables:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ETCD_ENDPOINTS=["etcd1:2379","etcd2:22379","etcd3:32379"]
ETCD_USERNAME=etcd_user
ETCD_PASSWORD=etcd_password
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now it is ready to accept and process the files.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -F "file1=@$HOME/Pictures/avatar.png" http://127.0.0.1:80/avatars/upload 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The response you can expect looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "status": "SUCCESS",
  "code": "SUCCESS",
  "message": "successfully uploaded 1 file(s)",
  "files": [
    {
      "url": "https://avatars.storage.example.com/avatars/abcdKDNJW_DDWse.jpg",
      "filename": "abcdKDNJW_DDWse.jpg",
      "originalFilename": "avatar.png",
      "mime": "image/jpeg",
      "size": 5892728,
      "status": "SUCCESS",
      "code": "FILE_SUCCESSFULLY_UPLOADED",
      "message": "file successfully uploaded"
    },
  ],
  "errors": [],
  "meta": {
    "totalUploads": 1,
    "successfulUploads": 1,
    "failedUploads": 0
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Log archive example
&lt;/h4&gt;

&lt;p&gt;To run our log archiver we can use capycmd command line application. Here's how you can do it with Docker:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker run \
    --name capyfile_server \
    --mount type=bind,source=./service-definition.yml,target=/etc/capyfile/service-definition.yml \
    --mount type=bind,source=/var/log/rotated-logs,target=/var/log/rotated-logs \
    --env CAPYFILE_SERVICE_DEFINITION_FILE=/etc/capyfile/service-definition.yml \
    --env MAX_LOG_FILE_AGE_RFC3339=$(date -d "30 days ago" -u +"%Y-%m-%dT%H:%M:%SZ") \
    --env AWS_LOGS_BUCKET=logs \
    --secret aws_access_key_id \
    --secret aws_secret_access_key \
    capyfile/capycmd:latest logs:archive
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Right now the app throws out some output that does not look very nice. But it can tell you what is happening and what the status of each file is. Remember, that it processes the files concurrently, so the output will have weird order. So you will see something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Running logs:archive service processor...

[/var/log/rotated-logs/access-2023-08-27.log] filesystem_input_read FINISHED file read finished
[/var/log/rotated-logs/access-2023-08-28.log] filesystem_input_read FINISHED file read finished
[/var/log/rotated-logs/access-2023-09-27.log] filesystem_input_read FINISHED file read finished
[/var/log/rotated-logs/access-2023-09-28.log] filesystem_input_read FINISHED file read finished
[/var/log/rotated-logs/access-2023-09-29.log] filesystem_input_read FINISHED file read finished
[/var/log/rotated-logs/access-2023-08-28.log] file_time_validate STARTED file time validation started
[/var/log/rotated-logs/access-2023-08-28.log] file_time_validate FINISHED file time is valid
[/var/log/rotated-logs/access-2023-08-27.log] file_time_validate STARTED file time validation started
[/var/log/rotated-logs/access-2023-09-27.log] file_time_validate STARTED file time validation started
[/var/log/rotated-logs/access-2023-08-27.log] file_time_validate FINISHED file time is valid
[/var/log/rotated-logs/access-2023-09-27.log] file_time_validate FINISHED file mtime is too new
[/var/log/rotated-logs/access-2023-09-29.log] file_time_validate STARTED file time validation started
[/var/log/rotated-logs/access-2023-09-27.log] s3_upload SKIPPED skipped due to "without_errors" target files policy
[/var/log/rotated-logs/access-2023-09-28.log] file_time_validate STARTED file time validation started
[/var/log/rotated-logs/access-2023-09-29.log] file_time_validate FINISHED file mtime is too new
[/var/log/rotated-logs/access-2023-08-28.log] s3_upload STARTED S3 file upload has started
[/var/log/rotated-logs/access-2023-09-28.log] file_time_validate FINISHED file mtime is too new
[/var/log/rotated-logs/access-2023-09-29.log] s3_upload SKIPPED skipped due to "without_errors" target files policy
[/var/log/rotated-logs/access-2023-08-27.log] s3_upload STARTED S3 file upload has started
[/var/log/rotated-logs/access-2023-09-27.log] filesystem_input_remove SKIPPED skipped due to "without_errors" target files policy
[/var/log/rotated-logs/access-2023-09-29.log] filesystem_input_remove SKIPPED skipped due to "without_errors" target files policy
[/var/log/rotated-logs/access-2023-09-28.log] s3_upload SKIPPED skipped due to "without_errors" target files policy
[/var/log/rotated-logs/access-2023-09-28.log] filesystem_input_remove SKIPPED skipped due to "without_errors" target files policy
[/var/log/rotated-logs/access-2023-08-27.log] s3_upload FINISHED S3 file upload has finished
[/var/log/rotated-logs/access-2023-08-28.log] s3_upload FINISHED S3 file upload has finished
[/var/log/rotated-logs/access-2023-08-27.log] filesystem_input_remove STARTED file remove started
[/var/log/rotated-logs/access-2023-08-27.log] filesystem_input_remove FINISHED file remove finished
[/var/log/rotated-logs/access-2023-08-28.log] filesystem_input_remove STARTED file remove started
[/var/log/rotated-logs/access-2023-08-28.log] filesystem_input_remove FINISHED file remove finished
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  In the end
&lt;/h2&gt;

&lt;p&gt;Capyfile is quite a new project and there is still a lot to do. Nevertheless, it is designed to give you as much flexibility as possible when it comes to building and configuring your pipeline, so it already quite successfully can cover some file processing routines.&lt;/p&gt;

&lt;p&gt;My next plan is to implement a couple of new operations, such as an operation with which you can run external commands and an operation for some basic video transcoding (will probably use FFmpeg as the backend). Another thing that I think is missing is the worker that will run the pipeline every N amount of time.  &lt;/p&gt;

&lt;p&gt;If you think this is something useful, you are welcome to contribute. Your feedback, suggestions, ideas, and PRs – this is something I really appreciate!&lt;/p&gt;

&lt;p&gt;Capyfile is maintained on GitHub. View the source, contribute, or report issues at:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/capyfile/capyfile"&gt;https://github.com/capyfile/capyfile&lt;/a&gt;&lt;/p&gt;

</description>
      <category>go</category>
      <category>tooling</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
