gorsn

package module
v0.0.0-...-49c777d Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 13, 2023 License: MIT Imports: 9 Imported by: 0

README

gorsn

godoc Go Report Card GitHub go.mod Go version MIT License

gorsn means Go Resource Scan Notifier. This is a simple & high-concurrent & options-rich cross-platform go-based library to periodically scan a folder and all its sub-content to get notified at any changes. Options are thread-safe and can be modified even during the program execution. The options allow for example to scale the number of workers/goroutines and to specify which kind of events we are interested in.

Features

A successful scan-notifier provided by gorsn.New method is an interface with below actions.

Action Description
Queue() <-chan Event provides a read-only channel to listen events from
Start(context.Context) error starts the scanner and events notifications routines
Stop() error stops the scanner and events notifications routines
Pause() error triggers to scanner to pause to avoid emitting events
Resume() error restarts the scanner and notifier after being paused
IsRunning() bool informs wether the scanner notifier is stopped or not
Flush() clears latest changes infos of files under monitoring

Installation

Just import the gorsn library as external package to start using it into your project. There are some examples into the examples folder to learn more.

[Step 1] - Download the package

$ go get github.com/jeamon/gorsn

[Step 2] - Import the package into your project

$ import "github.com/jeamon/gorsn"

[Step 3] - Optional: Clone the library to run some examples

$ git clone https://github.com/jeamon/gorsn.git
$ cd gorsn
$ go run examples/default-options/example.go
$ go run examples/custom-options/example.go

Usage

  • default options / settings
package main

import (
	"context"
	"log"
	"os"
	"os/signal"
	"syscall"
	"time"

	"github.com/jeamon/gorsn"
)

func main() {
	// step 1. define a path to a valid folder.
	root, err := os.Getwd() // lets use this package folder
	if err != nil {
		log.Fatal(err)
	}

	// step 2. use default options.
	var opts gorsn.Options

	// step 3. get an instance.
	sn, err := gorsn.New(root, &opts)
	if err != nil {
		log.Fatal(err)
	}

	// we can always change the settings at anytime in the program.
	opts.SetMaxWorkers(5).SetScanInterval(100 * time.Millisecond)

	// [optional] stop the scan notifier on CTRL+C.
	go func() {
		sigChan := make(chan os.Signal, 1)
		signal.Notify(sigChan, syscall.SIGINT, syscall.SIGQUIT,
			syscall.SIGTERM, syscall.SIGHUP, os.Interrupt)

		<-sigChan
		signal.Stop(sigChan)
		sn.Stop()
	}()

	// step 4. asynchronously receive events from the queue.
	go func() {
		for event := range sn.Queue() {
			log.Printf("received %q %s %s %v\n", event.Path, event.Type, event.Name, event.Error)
		}
	}()

	done := make(chan struct{})
	// step 5. start the scan notifier on the defined path.
	// lets run it as goroutine to bypass the blocking behavior.
	go func() {
		err = sn.Start(context.Background())
		if err != nil {
			log.Fatal(err)
		}
		done <- struct{}{}
	}()

	// lets change the settings on the fly.
	opts.SetMaxWorkers(10).
		SetScanInterval(500 * time.Millisecond).
		SetIgnoreNoChangeEvent(false)

	// wait the runner to exit
	<-done
}
  • custom options / settings
package main

import (
	"context"
	"log"
	"os"
	"os/signal"
	"regexp"
	"syscall"

	"github.com/jeamon/gorsn"
)

func main() {
	// step 1. define a path to a valid folder.
	// lets use this current folder so you can
	// observe any changes into your codebase.
	root := "./"

	// step 2. set some options.
	excludeRule := regexp.MustCompile(`.*(\.git).*`)
	// exclude `.git` folder. No include rule.
	opts := gorsn.RegexOpts(excludeRule, nil).
		// 5 events can wait into the queue.
		SetQueueSize(5).
		// 2 goroutines to build & emit events.
		SetMaxWorkers(2).
		// 0 sec - immediate, so no delay to scan.
		SetScanInterval(0)
		// others options keep their default values.

	// step 3. get an instance based on above settings.
	sn, err := gorsn.New(root, opts)
	if err != nil {
		log.Fatal(err)
	}

	// [optional] stop the scan notifier on CTRL+C.
	go func() {
		sigChan := make(chan os.Signal, 1)
		signal.Notify(sigChan, syscall.SIGINT, syscall.SIGQUIT,
			syscall.SIGTERM, syscall.SIGHUP, os.Interrupt)

		<-sigChan
		signal.Stop(sigChan)
		sn.Stop()
	}()

	// step 4. asynchronously receive events from the queue.
	go func() {
		for event := range sn.Queue() {
			log.Printf("received %q %s %s %v\n", event.Path, event.Type, event.Name, event.Error)
		}
	}()

	// step 5. start the scan notifier on the defined path.
	err = sn.Start(context.Background()) // blocks unless it fails or until stopped.
	if err != nil {
		log.Fatal(err)
	}
}

Contact

Feel free to reach out to me before any action. Feel free to connect on Twitter or linkedin

Documentation

Overview

Package gorsn implements utility routines for periodically monitoring a folder and its sub-folders content to detect any change such as file or folder deletion and creation along with content or permissions modification. Then it emits an appropriate event object on a consumable channel. The notifier system it provides could be stopped and status checked once started. It finally accepts a set of options which are safe to be modified by multiple goroutines even during its operations.

Index

Constants

View Source
const (
	CREATE   eventName = "CREATE"
	MODIFY   eventName = "MODIFY"
	DELETE   eventName = "DELETE"
	PERM     eventName = "PERM"
	ERROR    eventName = "ERROR"
	NOCHANGE eventName = "NOCHANGE"
)
View Source
const (
	FILE        pathType = "FILE"
	DIR         pathType = "DIRECTORY"
	SYMLINK     pathType = "SYMLINK"
	UNSUPPORTED pathType = "UNSUPPORTED"
)
View Source
const (
	DEFAULT_QUEUE_SIZE    = 10
	DEFAULT_MAX_WORKERS   = 1
	DEFAULT_SCAN_INTERVAL = 1 * time.Second
)

Variables

This section is empty.

Functions

This section is empty.

Types

type ErrorCode

type ErrorCode string

ErrorCode describes a failure on the resource scan notifier.

const (
	// Unexpected error
	ErrInternalError ErrorCode = "internal error"

	// Operations errors
	ErrInvalidRootDirPath ErrorCode = "invalid root directory path"
	ErrInitialization     ErrorCode = "error parsing root directory"
	ErrScanIsNotRunning   ErrorCode = "scan notifier is not running"
	ErrScanAlreadyStarted ErrorCode = "scan notifier has already started"
	ErrScanIsStopping     ErrorCode = "scan notifier is stopping"
	ErrScanIsNotReady     ErrorCode = "scan notifier is not (re)initialized"
	ErrScanIsNotPaused    ErrorCode = "scan notifier is not paused"
)

func (ErrorCode) Error

func (e ErrorCode) Error() string

Error returns the real error message.

type Event

type Event struct {
	Path  string
	Type  pathType
	Name  eventName
	Error error
}

type Options

type Options struct {
	// contains filtered or unexported fields
}

func RegexOpts

func RegexOpts(eregex, iregex *regexp.Regexp) *Options

func (*Options) SetIgnoreCreateEvent

func (o *Options) SetIgnoreCreateEvent(v bool) *Options

func (*Options) SetIgnoreDeleteEvent

func (o *Options) SetIgnoreDeleteEvent(v bool) *Options

func (*Options) SetIgnoreErrors

func (o *Options) SetIgnoreErrors(v bool) *Options

func (*Options) SetIgnoreFileEvent

func (o *Options) SetIgnoreFileEvent(v bool) *Options

func (*Options) SetIgnoreFolderContentEvent

func (o *Options) SetIgnoreFolderContentEvent(v bool) *Options

func (*Options) SetIgnoreFolderEvent

func (o *Options) SetIgnoreFolderEvent(v bool) *Options

func (*Options) SetIgnoreModifyEvent

func (o *Options) SetIgnoreModifyEvent(v bool) *Options

func (*Options) SetIgnoreNoChangeEvent

func (o *Options) SetIgnoreNoChangeEvent(v bool) *Options

func (*Options) SetIgnorePermEvent

func (o *Options) SetIgnorePermEvent(v bool) *Options
func (o *Options) SetIgnoreSymlink(v bool) *Options

func (*Options) SetMaxWorkers

func (o *Options) SetMaxWorkers(v int) *Options

func (*Options) SetQueueSize

func (o *Options) SetQueueSize(v int) *Options

func (*Options) SetScanInterval

func (o *Options) SetScanInterval(v time.Duration) *Options

type ScanNotifier

type ScanNotifier interface {
	// Queue returns the channel to listen on for receiving changes events.
	// The returned channel is read-only to avoid closing or writing on.
	Queue() <-chan Event

	// Start begins periodic scanning of root directory and emitting events.
	Start(context.Context) error

	// Stop aborts the scanning of root directory and sending events.
	Stop() error

	// IsRunning reports whether the scan notifier has started.
	IsRunning() bool

	// Flush clears internal cache history of files and directories under monitoring.
	// Once succeeded, `CREATE` is the next event for each item under monitoring.
	// This could be used directly after initialization of the scan notifier instance
	// in order to receive the list of item (via `CREATE` event) inside root directory.
	// Calling this while the scan notifier has started will make the scanner to detect
	// each item like newly created into the root directory so the notifier will emit
	// `CREATE` event for those items almost immediately.
	Flush()

	// Pause instructs the scanner to escape at each polling interval so no changes
	// detection will happen then no new events will be sent.
	// Use Resume() to restart the normal scanning and event notification processes.
	Pause() error

	// Resume restarts the scanner and notifier after being into `paused` state.
	Resume() error
}

ScanNotifier is an interface which defines a set of available actions.

func New

func New(root string, opts *Options) (ScanNotifier, error)

New provides an initialized object which satisfies the ScanNotifier interface. It initializes itself based on the `root` value which is expected to be a path to an accessible directory. The content of the root directory will be parsed and loaded based on the options provided by `opts`. It returns and error which wraps `ErrInvalidRootDirPath` in case the root path is not an accessible directory. `ErrInitialization` means the initialization encoutered an error.

Directories

Path Synopsis
examples

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL