Giter Site home page Giter Site logo

dargo's People

Contributors

jwells131313 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

Forkers

c6o hitorisensei

dargo's Issues

Create a Provider for scopes with different lifecycles

Scopes with different lifecycles have problems when being injected into each other. For example, image a Context scope service being injected into a Singleton scope service. When the Context changes if you just inject the raw service it'll be wrong in the Singleton service. This is unfortunate, and the only real answer I can think of is the old JSR-330 style Provider. So, something like this:

type Foo struct {
BarProvider Provider inject:"Bar"
}

Where provider looks something like this maybe:

type Provider interface {
Get() (interface{}, error)
GetAll() ([]interface{}, error)
}

Might also want to use some of the concepts from IterableProvider in hk2

Beef up Provider documentation

The documentation in the README for Provider does not have enough information in it. Beef it up, maybe adding a small section for each API of Provider

Custom Injection Resolvers

What if the user doesn't like the inject:"whatever" tag on their structs?

They can provide a CustomInjectionResolver and then use whatever sort of tag they want on the structure! This is how hk2 does this, and it does come in useful in many different scenarios.

The idea is named services in a specific namespace, and the first one that finds a tag wins. So in theory a user could override the system supplied "inject" custom injection resolver

Optional Injection

Need a way to say an injection is optional. Maybe something like:

type Foo struct {
Foo Foo inject:"Foo,optional"
}

or something like that

ValidationService

Add a ValidationService for security, just like in hk2.

Once the ValidationService is in and documented I would say that's a point where we can declare a new release of dargo

Dargo doesn't handle circular dependencies

Scenario:
Singleton Service A depends on Singleton Service B
Singleton Service B depends on Singleton Service C
Singleton Service C depends on Singleton Service A

All dependencies are annotated.

Problem:
Services are left uninitialized since they all depend on each other.

Expected Behaviour:
I expected, similar to other frameworks I used on a different languages, The services would be first initialized and created, and only then dependencies would be passed to each other, avoiding this behaviour that typically occurs on constructor injection only.

Workaround:
Remove the annotations. After injection container initializes all services, manually assign the dependencies between each service.

Creating deep services fails

From docs:

Any depth of injection is supported (ServiceA can depend on ServiceB which depends on ServiceC and so on). A service can also depend on as many services as it would like (ServiceA can depend on service D, E and F etc). Howerver, services cannot have circular dependencies.

Creating larger than 7-depth services fails: https://go.dev/play/p/QwAmt1aIbiE

panic: 1. write lock is not held by this thread
2. an error occurred while getting the dependencies of default#Component3.1.5
3. an error occurred while getting the dependencies of default#Component4.1.6
4. an error occurred while getting the dependencies of default#Component5.1.7
5. an error occurred while getting the dependencies of default#Component6.1.8
6. an error occurred while getting the dependencies of default#Component7.1.9
7. an error occurred while getting the dependencies of default#Component8.1.10

goroutine 1 [running]:
main.main()
	/tmp/sandbox741982879/prog.go:58 +0xa5

In real-project we also experienced IOC error: function called from non-goethe thread and sometimes code just hangs on goethe lock acquire in gotethe cache/cache.go:243.

Workaround

If the depth of creation is smaller (ex. something existed previously), it works: https://go.dev/play/p/SVmmLqr3_6I

Optimize Lookups

Lookups can be done a lot faster if we can know the Namespace and Name involved.

Modify Filter to supply these (they can return "" for any) and then keep descriptors indexed
by namespace/name internally

Support injecting sub-struct

When running the following code available on Go Playground:

package main

import (
	"fmt"

	"github.com/jwells131313/dargo/ioc"
)

type ConfigA struct {
	Flag1 int
	Flag2 int
}

type ConfigB struct {
	Flag3 int
	Flag4 int
}

type Config struct {
	ConfigA
	ConfigB
}

type ServiceA struct {
	ServiceConfig *ConfigA `inject:"Config"`
}

func main() {
	locator, err := ioc.CreateAndBind("testing", func(binder ioc.Binder) error {
		binder.Bind("Config", &Config{}).InScope(ioc.Singleton)
		binder.Bind("ServiceA", &ServiceA{}).InScope(ioc.Singleton)
		return nil
	})
	if err != nil {
		return
	}

	// The next line fails
	raw, err := locator.GetDService("ServiceA")
	if err != nil {
		fmt.Printf("ERROR %v+", err)
		return
	}

	fmt.Printf("%v+", raw)
}

I get the error:

ERROR 1. reflect.Set: value of type *main.Config is not assignable to type *main.ConfigA
2. an error occurred while injecting the dependencies of default#ServiceA.1.4+

This makes sense because one can't do ConfigA = Config, you have to do ConfigA = Config.ConfigA. I am instead having to use Qualifiers to bind Config.ConfigA to Config@ConfigA etc.

This could be a case that the internal resolver can handle using Reflection.

I may be able to submit a PR for this if you could point me to where the best place to place this logic would be. I tried writing a custom resolver however, I needed to call GetDService to get the Config service in my custom resolver and the system errored out thinking there was a circular dependency.

Thank you

Wrap all calls to user code in panic-safe wrappers

Users write... uh... code that sometimes panics.

Panics from user callbacks should not cause dargo API to panic. Instead they should all be handled properly.

All calls to things like ErrorService and ValidationService should be wrapped and all panics handled appropriately

Allow for names with namespace and qualifiers in inject

I should be allowed to specify the namespace and qualifiers for injected services. Possibly something like this:

type Foo struct {
Bar Bar inject:"some/name/space#Bar@Red@Blue"
}

In the above case the namespace would be "some/name/space", the name would be "Bar" and it would want qualifiers "Red" and "Blue"

Create inject method on ServiceLocator

The inject method will inject all known dependencies into the already existing structure without having Dargo manage the structure passed in. This is very useful for people just trying Dargo out who do not want to completely buy in but want to go "IoC" light.

See also hk2 inject

JustInTime Injection Resolver

A Just-in-time injection resolver is a second-chance when a service cannot be found. It's very useful when integrating with other systems, or when building bridges between systems. It's also useful for remote services that might be found only at runtime.

Implement Events

Events allow services to communicate with each other without prior association.

It should be pluggable so that subscribers can get any sort of quality of service that the system needs as in the hk2 system

Implement instance lifecycle listeners

Instance lifecycle listeners are very useful for debugging the internals of the dargo system and for other reasons. Note that instance listeners are different from Validation listeners because validation listeners are for lookups/injections of services (which may already exist). Instance listeners are different from Configuration listeners because configuration listeners are only for bind/unbind.

Instance listeners are called at specific points in the lifecycle of an actual service object:

PRE_PRODUCTION
POST_PRODUCTION
PRE_DESTRUCTION

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.