-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Lawrence Zawila <113581282+darkmatterpool@users.noreply.github.com>
- Loading branch information
1 parent
8b71be7
commit 6a0f52f
Showing
11 changed files
with
375 additions
and
52 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,52 @@ | ||
package dummypay | ||
|
||
import ( | ||
"fmt" | ||
"syscall" | ||
"time" | ||
) | ||
|
||
// Config is the configuration for the dummy payment connector. | ||
type Config struct { | ||
Directory string | ||
// Directory is the directory where the files are stored. | ||
Directory string `json:"directory" yaml:"directory" bson:"directory"` | ||
|
||
// FilePollingPeriod is the period between file polling. | ||
FilePollingPeriod time.Duration `json:"filePollingPeriod" yaml:"filePollingPeriod" bson:"filePollingPeriod"` | ||
|
||
// FileGenerationPeriod is the period between file generation. | ||
FileGenerationPeriod time.Duration `json:"fileGenerationPeriod" yaml:"fileGenerationPeriod" bson:"fileGenerationPeriod"` | ||
} | ||
|
||
// String returns a string representation of the configuration. | ||
func (cfg Config) String() string { | ||
return fmt.Sprintf("directory: %s, filePollingPeriod: %s, fileGenerationPeriod: %s", | ||
cfg.Directory, cfg.FilePollingPeriod, cfg.FileGenerationPeriod) | ||
} | ||
|
||
// Validate validates the configuration. | ||
func (cfg Config) Validate() error { | ||
// require directory path to be present | ||
if cfg.Directory == "" { | ||
return ErrMissingDirectory | ||
} | ||
|
||
// check if RW access is available for the given directory | ||
if err := syscall.Access(cfg.Directory, syscall.O_RDWR); err != nil { | ||
return fmt.Errorf("directory is not accessible: %w", err) | ||
} | ||
|
||
// check if file polling period is set properly | ||
if cfg.FilePollingPeriod <= 0 { | ||
return fmt.Errorf("filePollingPeriod must be greater than 0: %w", | ||
ErrFilePollingPeriodInvalid) | ||
} | ||
|
||
// check if file generation period is set properly | ||
if cfg.FileGenerationPeriod <= 0 { | ||
return fmt.Errorf("fileGenerationPeriod must be greater than 0: %w", | ||
ErrFileGenerationPeriodInvalid) | ||
} | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,62 @@ | ||
package dummypay | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
|
||
"github.com/numary/go-libs/sharedlogging" | ||
"github.com/numary/payments/pkg/bridge/task" | ||
) | ||
|
||
// connectorName is the name of the connector. | ||
const connectorName = "dummypay" | ||
|
||
// Connector is the connector for the dummy payment connector. | ||
type Connector struct { | ||
logger sharedlogging.Logger | ||
cfg Config | ||
} | ||
|
||
// Install executes post-installation steps to read and generate files. | ||
// It is called after the connector is installed. | ||
func (c *Connector) Install(ctx task.ConnectorContext[TaskDescriptor]) error { | ||
if err := ctx.Scheduler().Schedule(newTaskReadFiles(), true); err != nil { | ||
return fmt.Errorf("failed to schedule task to read files: %w", err) | ||
} | ||
|
||
if err := ctx.Scheduler().Schedule(newTaskGenerateFiles(), true); err != nil { | ||
return fmt.Errorf("failed to schedule task to generate files: %w", err) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
// Uninstall executes pre-uninstallation steps to remove the generated files. | ||
// It is called before the connector is uninstalled. | ||
func (c *Connector) Uninstall(ctx context.Context) error { | ||
c.logger.Infof("Removing generated files from '%s'...", c.cfg.Directory) | ||
|
||
err := removeFiles(c.cfg) | ||
if err != nil { | ||
return fmt.Errorf("failed to remove generated files: %w", err) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
// Resolve resolves a task execution request based on the task descriptor. | ||
func (c *Connector) Resolve(descriptor TaskDescriptor) task.Task { | ||
c.logger.Infof("Executing '%s' task...", descriptor.Key) | ||
|
||
return handleResolve(c.cfg, descriptor) | ||
} | ||
|
||
// NewConnector creates a new dummy payment connector. | ||
func NewConnector(logger sharedlogging.Logger, cfg Config) *Connector { | ||
return &Connector{ | ||
logger: logger.WithFields(map[string]any{ | ||
"component": "connector", | ||
}), | ||
cfg: cfg, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,35 +1,51 @@ | ||
package dummypay | ||
|
||
import ( | ||
"fmt" | ||
"time" | ||
|
||
"github.com/numary/go-libs/sharedlogging" | ||
"github.com/numary/payments/pkg/bridge/integration" | ||
"github.com/numary/payments/pkg/bridge/task" | ||
) | ||
|
||
type loader struct{} | ||
|
||
// Name returns the name of the connector. | ||
func (l *loader) Name() string { | ||
return connectorName | ||
} | ||
|
||
// AllowTasks returns the amount of tasks that are allowed to be scheduled. | ||
func (l *loader) AllowTasks() int { | ||
return 10 | ||
} | ||
|
||
const ( | ||
// defaultFilePollingPeriod is the default period between file polling. | ||
defaultFilePollingPeriod = 10 * time.Second | ||
|
||
// defaultFileGenerationPeriod is the default period between file generation. | ||
defaultFileGenerationPeriod = 5 * time.Second | ||
) | ||
|
||
// ApplyDefaults applies default values to the configuration. | ||
func (l *loader) ApplyDefaults(cfg Config) Config { | ||
if cfg.FileGenerationPeriod == 0 { | ||
cfg.FileGenerationPeriod = defaultFileGenerationPeriod | ||
} | ||
|
||
if cfg.FilePollingPeriod == 0 { | ||
cfg.FilePollingPeriod = defaultFilePollingPeriod | ||
} | ||
|
||
return cfg | ||
} | ||
|
||
// Load returns the connector. | ||
func (l *loader) Load(logger sharedlogging.Logger, config Config) integration.Connector[TaskDescriptor] { | ||
return NewConnector(logger, config) | ||
} | ||
|
||
// NewLoader creates a new loader. | ||
func NewLoader() integration.Loader[Config, TaskDescriptor] { | ||
loader := integration. | ||
NewLoaderBuilder[Config, TaskDescriptor](connectorName). | ||
WithLoad(func(logger sharedlogging.Logger, config Config) integration.Connector[TaskDescriptor] { | ||
return integration.NewConnectorBuilder[TaskDescriptor](). | ||
WithInstall(func(ctx task.ConnectorContext[TaskDescriptor]) error { | ||
return ctx.Scheduler().Schedule(newTaskReadFiles(), true) | ||
}). | ||
WithResolve(func(descriptor TaskDescriptor) task.Task { | ||
switch descriptor.Key { | ||
case taskKeyReadFiles: | ||
return taskReadFiles(config) | ||
case taskKeyIngest: | ||
return taskIngest(config, descriptor) | ||
} | ||
|
||
return func() error { | ||
return fmt.Errorf("key '%s': %w", descriptor.Key, ErrMissingTask) | ||
} | ||
}). | ||
Build() | ||
}). | ||
Build() | ||
|
||
return loader | ||
return &loader{} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package dummypay | ||
|
||
import payments "github.com/numary/payments/pkg" | ||
|
||
// payment represents a payment structure used in the generated files. | ||
type payment struct { | ||
payments.Data | ||
Reference string `json:"reference" bson:"reference"` | ||
Type string `json:"type" bson:"type"` | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
package dummypay | ||
|
||
import ( | ||
"fmt" | ||
"os" | ||
"strings" | ||
) | ||
|
||
// removeFiles removes all files from the given directory. | ||
// Only removes files that has generatedFilePrefix in the name. | ||
func removeFiles(config Config) error { | ||
dir, err := os.ReadDir(config.Directory) | ||
if err != nil { | ||
return fmt.Errorf("failed to open directory '%s': %w", config.Directory, err) | ||
} | ||
|
||
// iterate over all files in the directory | ||
for _, file := range dir { | ||
// skip files that do not match the generatedFilePrefix | ||
if !strings.HasPrefix(file.Name(), generatedFilePrefix) { | ||
continue | ||
} | ||
|
||
// remove the file | ||
err = os.Remove(fmt.Sprintf("%s/%s", config.Directory, file.Name())) | ||
if err != nil { | ||
return fmt.Errorf("failed to remove file '%s': %w", file.Name(), err) | ||
} | ||
} | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,33 @@ | ||
package dummypay | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/numary/payments/pkg/bridge/task" | ||
) | ||
|
||
// taskKey defines a unique key of the task. | ||
type taskKey string | ||
|
||
// TaskDescriptor represents a task descriptor. | ||
type TaskDescriptor struct { | ||
Key taskKey | ||
FileName string | ||
} | ||
|
||
func (td TaskDescriptor) Is(key taskKey) bool { | ||
return td.Key == key | ||
// handleResolve resolves a task execution request based on the task descriptor. | ||
func handleResolve(config Config, descriptor TaskDescriptor) task.Task { | ||
switch descriptor.Key { | ||
case taskKeyReadFiles: | ||
return taskReadFiles(config) | ||
case taskKeyIngest: | ||
return taskIngest(config, descriptor) | ||
case taskKeyGenerateFiles: | ||
return taskGenerateFiles(config) | ||
} | ||
|
||
// This should never happen. | ||
return func() error { | ||
return fmt.Errorf("key '%s': %w", descriptor.Key, ErrMissingTask) | ||
} | ||
} |
Oops, something went wrong.