<div dir="ltr"><div><div>There is really one practical issue that is driving this convo (I think):  Django's file upload handling wants to save a file when we receive it. We also don't want to be moving around files. Therefore we must save the file in the right place on the first save().<br><br></div><div>So given ^, the question reduces to: "Where do we want to save a file that backs an Artifact?" We can do that one of two ways: randomly or orderly. Randomly would be inventing a uuid for each file and having that make the path to the file unique. An orderly way of doing it would be to have an digest be used instead of a uuid. Here are some path examples:<br><br></div><div>random_path_example (random uuid):    <span class="gmail-im">MEDIA_ROOT/artifact/uuid[0:2<wbr>]/uuid[2:]<br></span></div><div><span class="gmail-im">orderly_path_example (sha256 is the binary's digest):    </span><span class="gmail-im">MEDIA_ROOT/artifact/digest[0:2<wbr>]/digest[2:]</span></div><div><br></div><div>Random assignment is straightforward, and it also allows one Artifact to serve exactly one content unit allowing CASCADE delete's to handle cleanup easily. The problem with random assignment is that it prevents an important down-the-road use case:  "as a user who has a file backup but not a database backup, I can recover my data without having to re-download all of my content from remotes". Specifically, if Artifact's paths are randomly chosen at upload time then if someone hands you a disk of Artifacts and asks you to sync EPEL, there is no way Pulp can reasonably recognize content it has on disk as already existing there.<br><br></div><div>This is where content addressable storage comes in. If the remoteArtifact has the sha256 hash value set from the remote metadata that was fetched, Pulp's changesets could recognize data on disk as already downloaded. A random layout can never do that. A tertiary outcome of using Content Addressable Store is that now each file backing an Artifact can only be stored on the filesystem. I say "tertiary outcome" and not "downside" because even though it's harder for us to implement, users would definitely see it as a benefit that Pulp can't duplicate content at an Architectural level.<br><br></div><div>Please send thoughts/ideas.<br><br></div><div>-Brian<br></div></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Jun 29, 2017 at 9:16 AM, Michael Hrivnak <span dir="ltr"><<a href="mailto:mhrivnak@redhat.com" target="_blank">mhrivnak@redhat.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">Thanks for that explanation. That makes sense. I would describe this as saying there is a many-to-many relationship between Content and Artifact, and the ContentArtifact is the "glue" or "through" table.<div><br></div><div>And again to just understand why... are we deliberately trying to prioritize a use case where one artifact is shared by multiple Content units? Can someone talk about the pros and cons of that within the context of this proposal? I expect it could save a small portion of disk space, but maybe not very much. Pulp does a pretty good job of de-duplicating at the Content level. Changing to a m2m relationship would definitely add more complexity though, and that's the aspect I'm interested in comparing to what value we are seeking.<br><div><br></div><div>Separate from that relationship question, we have a use case that the direct-to Artifact workflow does not cover. There are multiple unit types where a user wants to upload a single file that represents multiple content units, and let pulp create one or more content units based on that file. For example, a docker manifest and its blobs all get saved to disk together (by a separate tool) and then uploaded as a tarball that Pulp can receive and process together. We could ask the upload client to open up the tarball and upload files individually I suppose. That puts more burden on the client though.</div></div><div><br></div><div>Another example: a user can upload a comps.xml file, and pulp will parse it to create as many units as it finds in the XML. Pulp does not keep that comps.xml file, so in the proposed workflow, it would need to delete the Artifact at the end. It seems unexpected to utilize an Artifact as temporary storage in this way.</div><div><br></div><div>I suspect we'll find more use cases like this. Thoughts? Is the FileUpload really worth eliminating? What I like about the current upload workflow, and the FileUpload workflow, is that it allows the plugin to receive any file or set of files that make sense within its domain, and then use that set of files to create units however it sees fit. It is difficult to get more prescriptive than that at the platform/core level.</div></div><div class="HOEnZb"><div class="h5"><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Jun 29, 2017 at 8:47 AM, Dennis Kliban <span dir="ltr"><<a href="mailto:dkliban@redhat.com" target="_blank">dkliban@redhat.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><span>On Thu, Jun 29, 2017 at 7:40 AM, Michael Hrivnak <span dir="ltr"><<a href="mailto:mhrivnak@redhat.com" target="_blank">mhrivnak@redhat.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><span class="m_-3552331345692477249m_8953507853256652190gmail-"><br><div class="gmail_quote">On Thu, Jun 29, 2017 at 7:22 AM, Dennis Kliban <span dir="ltr"><<a href="mailto:dkliban@redhat.com" target="_blank">dkliban@redhat.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><span><div><br></div></span><div>The many to many relationship is between Artifact and ContentArtifact. This allows a content unit to have multiple Artifacts associated with it.</div></blockquote></div><br></span>Could you elaborate on this? A content unit can have multiple artifacts just by artifact having a foreign key to a content unit. That's the one-to-many relationship we have on the model now in 3.0-dev.</div><div class="gmail_extra"><br></div><div class="gmail_extra">Also, what is a ContentArtifact?<span class="m_-3552331345692477249m_8953507853256652190gmail-"><br><br clear="all"></span></div></div></blockquote><div><br></div></span><div>Here are some definitions for the new proposal:<br></div><ul><li>Artifact - a file stored in pulp</li><li>Content - a named collection of 0 or more Artifacts that can be associated with a repository as a single unit</li><li>ContentArtifact - a relationship between an Artifact and Content. There is 0 or more ContentArtifacts for each Content.</li><li>Repository - A named collection of content.</li><li>RepositoryContent - a relationship between Content and Repository. </li></ul><div><br>In the proposal we have in the MVP we have the following:<br><ul><li>FileUpload - Uploaded file that is used to create Artifacts and is then removed (definition for this is not present in the glossary of MVP)<br></li><li>Artifact - A file associated with one content (unit). Artifacts are not shared between content (units). Create a content unit using an uploaded file ID as the source for its metadata. Create Artifacts associated with the content unit using an uploaded file ID for each; commit as a single transaction.</li><li>Content (unit) - A single piece of content manged by Pulp. Each file associated with a content (unit) is called an Artifact. Each content (unit) may have zero or many Artifacts.</li><li>Repository - A named collection of content.</li><li>RepositoryContent - a relationship between Content and Repository (also not in the glossary of the MVP)<br></li></ul><p>In the MVP in order to add a unit to a repository, a user would:</p><ol><li>Create a FileUpload by uploading a file<br></li><li>Create an Artifact and a Content with one API call</li><li>Associate a Content with a Repository</li><li>Delete the FileUpload (or some cleanup job would do that for the user)</li></ol><p>The newly proposed workflow:</p><ol><li>Create an Artifact by uploading a file</li><li>Create a Content by specifying which Artifact(s) belongs to the Content and their relative paths inside the unit. This creates ContentArtifacts for each relationship.</li><li>Associate a Content with a repository.</li></ol><p>In the MVP workflow, once an FileUpload is deleted, it's hard to create another Content from that file. I am sure we can come up with a way to do it, but it won't be as straight forward as the above workflow.</p><p></p></div><span><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><span class="m_-3552331345692477249m_8953507853256652190gmail-"><div><br></div>-- <br><div class="m_-3552331345692477249m_8953507853256652190gmail-m_7153167500244933577gmail_signature"><div dir="ltr"><p style="color:rgb(0,0,0);font-family:overpass-mono,monospace;font-size:10px;margin:0px;padding:0px"><span style="margin:0px;padding:0px">Michael</span> <span style="margin:0px;padding:0px">Hrivnak</span></p><p style="color:rgb(0,0,0);font-family:overpass-mono,monospace;font-size:10px;margin:0px;padding:0px"></p><span style="color:rgb(0,0,0);font-family:overpass-mono,monospace;font-size:10px;margin:0px;padding:0px"><span style="margin:0px;padding:0px">Principal Software Engineer</span><span style="margin:0px;padding:0px">, <span style="margin:0px;padding:0px">RHCE</span></span> </span><span style="color:rgb(0,0,0);font-family:overpass-mono,monospace;font-size:10px"></span><br style="color:rgb(0,0,0);font-family:overpass-mono,monospace;font-size:10px;margin:0px;padding:0px"><p style="color:rgb(0,0,0);font-family:overpass-mono,monospace;font-size:10px;margin:0px;padding:0px">Red Hat</p></div></div>
</span></div></div>
</blockquote></span></div><br></div></div>
</blockquote></div><br><br clear="all"><div><br></div>-- <br><div class="m_-3552331345692477249gmail_signature" data-smartmail="gmail_signature"><div dir="ltr"><p style="color:rgb(0,0,0);font-family:overpass-mono,monospace;font-size:10px;margin:0px!important;padding:0px!important"><span style="margin:0px!important;padding:0px!important">Michael</span> <span style="margin:0px!important;padding:0px!important">Hrivnak</span></p><p style="color:rgb(0,0,0);font-family:overpass-mono,monospace;font-size:10px;margin:0px!important;padding:0px!important"></p><span style="color:rgb(0,0,0);font-family:overpass-mono,monospace;font-size:10px;margin:0px!important;padding:0px!important"><span style="margin:0px!important;padding:0px!important">Principal Software Engineer</span><span style="margin:0px!important;padding:0px!important">, <span style="margin:0px!important;padding:0px!important">RHCE</span></span> </span><span style="color:rgb(0,0,0);font-family:overpass-mono,monospace;font-size:10px"></span><br style="color:rgb(0,0,0);font-family:overpass-mono,monospace;font-size:10px;margin:0px!important;padding:0px!important"><p style="color:rgb(0,0,0);font-family:overpass-mono,monospace;font-size:10px;margin:0px!important;padding:0px!important">Red Hat</p></div></div>
</div>
</div></div><br>______________________________<wbr>_________________<br>
Pulp-dev mailing list<br>
<a href="mailto:Pulp-dev@redhat.com">Pulp-dev@redhat.com</a><br>
<a href="https://www.redhat.com/mailman/listinfo/pulp-dev" rel="noreferrer" target="_blank">https://www.redhat.com/<wbr>mailman/listinfo/pulp-dev</a><br>
<br></blockquote></div><br></div>