jeudi 13 février 2020

Cycle dependency in Go

I know about cycle dependencies, but in my situation I really don't see the solution.

Let's assume there is Storage service which consists of small parts (Files service and Permissions service and others):

structure

In my main.go file I have NewService() function, which creates all dependent services:

package storage

import (
    "github.com/storage/files"
    "github.com/storage/permissions"
)

type Service interface {
    GetFileService() files.Service
    GetPermissionService() permissions.Service
}

type service struct {
    Files       files.Service
    Permissions permissions.Service
}

func NewService() Service {
    s := &service{}
    s.Files = files.NewService()
    s.Permissions = permissions.NewService()
    return s
}

func (s *service) GetFileService() files.Service {
    return s.Files
}

func (s *service) GetPermissionService() permissions.Service {
    return s.Files
}

In files/service.go I do file's management. But I need to get Permissions service from there to work with permissions. Look example code below:

package files

import (
    "errors"

    // And here is cycle dependency.
    // But I should import it somehow to be able to call all
    // other services I need (see DownloadFile function below)
    storage "github.com/storage"
)

type Service interface {
    DownloadFile(fileId string) (*File, error)
}

type service struct {
    ss storage.Service
}

func NewService(ss storage.Service) Service {
    return &service{
        ss: ss,
    }
}

func (s *service) DownloadFile(fileId string) (*File, error) {
    // Here I get permission service and call it's method
    ok, err := s.ss.GetPermissionService().CanDownload(fileId)
    if err != nil {
        return nil, err
    }
    if !ok {
        return nil, errors.New("forbidden")
    }

    // User has permission to download file
    // go to repo and exchange fileId to filePath
    // read file from disk and return it ...
}

How can I solve this cycle dependency? I can't merge permissions with files as permissions service is used by others components too. So the main goal is to be able to get from each service to each service. Yes, it sound weird as it is a cycle dependency, but ...

Aucun commentaire:

Enregistrer un commentaire