#Artifacts ๐งต
1 messages ยท Page 1 of 1 (latest)
๐งต
Creating a separate thread to keep #1468070450524459029 focused on ongoing implementation work, this is for the next layer of improvements ("phase 3") with artifacts, dynamic checks, workspace provenance etc
Artifacts ๐งต
@wintry vector @hazy meteor I'm wondering about constructors... I believe the engine & dagql have a first-class constructor concept that we don't fully expose to clients & module devs, correct?
I'm wondering if you have any thoughts on whether we should expose more; and if so, how?
I'm encountering this topic because with "artifact" (3d phase of modules v2) we try to present to the user a more object-oriented model, and there is some impedance mismatch with the strongly function-oriented model we present so far
So, I'm looking for wiggle room ๐
Also I noticed that quite a few modern "X as code" products look like "new(bla)", the native DX is very object-oriented in a way that we are not. I even remember that one HN thread that called us out on that, saying "your DX feels like dusty java builder pattern, I would prefer this style"
@wintry vector have you ever been tempted to expose a concept of constructor for any module? kind of like Go's new() and the Go-native pattern of a package exposing NewFoo() or just foo.New() ?
Seems interweaved with the problem of load() and the explosion of top-level loadXXXFromID() maybe new and load come in a set?
doesn't that already exist? 
do you mean for any type in the module?
(rather than just the main type)
(i have WIP for this on https://github.com/dagger/dagger/pull/12041 - paused to focus on workspace-plumbing)
yeah
i always come around to it being simpler to just chain from the main type, and never had a need for anything else in the end
what's the motivation?
i see the temptation for new though especially in light of adding with
something like this?: new { apko(args...): Apko!, wolfi(args...): Wolfi! }
just opening all the drawers to make sure every available tool is accounted for, as I churn on Artifacts design
Hello! Yeah, I totally get Dagger is more "hey client please create a DAG via RPC calls", but just making something up in 30 seconds, like this is what I had in mind:https://gist.github.com/stephenh/8c7823229dfffc0347c2e94a3c9...Like I'm still building a DAG, but by creating objects with "kinda POJOs" (doesn't have to be literally POJOs) and the...
The HN comment I was referring to ๐
Hello! Yeah, I totally get Dagger is more "hey client please create a DAG via RPC calls", but just making something up in 30 seconds, like this is what I had in mind:
const build = new TypeScriptBuild({
workDir: "/src",
destDir: "/dest",
})
const test = new JestSuite(
input: build
)
const container = new ContainerService(, {
from: "typescript",
workDir: build,
exportPorts: 8080,
})
Like I'm still building a DAG, but by creating objects with "kinda POJOs" (doesn't have to be literally POJOs) and then stitching them together, like the outputs of 1 construct (the build) can be used as inputs to the other constructs (tests & container).
Not endorsing that particular suggestion btw
one pov is to basically re-frame around constructable objects, rather than core vs. modules
no it's interesting
Just opening drawers ๐
migration plan would be pretty easy; modules don't change at all
instead of
Query { core, dep1, dep2, entrypoint1, entrypoint2 }
orQuery { container, directory, dep1, dep2, entrypoint1, entrypoint2 }(current)
it'd just be:Query { new, entrypoint1, entrypoint2 }(edit: typeddagoriginally, tangential thought)
maybe?
@wintry vector fun fact: ObjectTypeDef already has a constructor field..
yeah - it works that way already ๐
So kind of a semihidden feature no?
i don't actually know what happens if you set it on multiple objects 
i imagine nothing gets exposed though
In theory a runtime could already register a non-main object with a constructor? What would the engine do with it though
i'm pretty sure it'll just be ignored, everything looks up a module's object by name and only refer to that for the constructor
(...and has to be careful to look up by OriginalName, since modules can be renamed)
what would renaming even mean in this case
- would we need to support a mapping from object name to new name? feels weird. just special case the main object? but that implies there's still a special object. wat do
maybe we wouldn't need to support renaming if constructors become a first-class thing?
Mm actually nevermind you still need a way to install 2 modules that call themselves "go"
Rename would apply to all types:
type Foo {}
func New() Foo
type App struct {}
type Site struct {}
No rename:
new("Foo")
new("FooApp")
new("FooSite")
If module is renamed to "bar":
new("Bar")
new("BarApp")
new("BarSite")
@wintry vector too early to tell for sure, but I'm in the thick of the design maze, and the constructor stuff above ๐ might be a major unlock ๐ Will report back soon
how'd that turn out? trying to peek ahead and get an idea of the fate of core { ... } vs. some unified per-type constructor scheme
Polishing
Last night it was growing into a major dependency / stepping stone so I went pretty far into spec-ing it.
Then I went through a few rounds of churn and simplification on the upper layers
Now this morning I realize, it's doable without touching the constructor schema - but I still have the spec, so spinning it out as a separate track with no dependency ๐
I dabbled with the idea of supporting multiple constructors per module, had it in the bag, BUT it breaks constructor args as config... So I scoped it down to: still just one constructor per module, but cleaner schema, constructor-oriented, and core is just another module
Separately: I think I have a solution for test filtering ๐ Focusing on that atm
gotcha - so having a core { ... } is still in the cards, as a way to mitigate client side filtering?