diff --git a/Project.toml b/Project.toml index f95c312..9eea204 100644 --- a/Project.toml +++ b/Project.toml @@ -3,7 +3,7 @@ uuid = "f3e6a059-199c-4ada-8143-fcefb97e6165" keywords = ["navability", "navigation", "slam", "sdk", "robotics", "robots"] desc = "NavAbility SDK: Access NavAbility Cloud factor graph features. Note that this SDK and the related API are still in development. Please let us know if you have any issues at info@navability.io." authors = ["NavAbility "] -version = "0.8.5" +version = "0.8.6" [deps] Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" @@ -24,7 +24,7 @@ UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4" Aqua = "0.8" Base64 = "1.10" Dates = "1.10" -DistributedFactorGraphs = "0.25.2" +DistributedFactorGraphs = "0.25.2, 0.26" DocStringExtensions = "0.8, 0.9" Downloads = "1" GraphQLClient = "0.7" diff --git a/docs/PublicAPI_design.jl b/docs/PublicAPI_design.jl new file mode 100644 index 0000000..ebae116 --- /dev/null +++ b/docs/PublicAPI_design.jl @@ -0,0 +1,53 @@ +### Public API - supported in all SDKs + +# All funcitons should follow DistributedFactorGraphs.jl and we use Julia here to define the signitures. + +# Other lanuages should follow DFG.jl/NvaSDK.jl as closely as possible with the following exceptions +# - labels are Symbols in julia and strings elsewhere. +# - mutation in julia is done with ! at the end of the function name and not in other languages. +# - notably C and Rust do not support function overloading and may also be different or more explicit and perhaps using adjectives. + +## Structs + +## Functions + +### Singular `get` + +getVariable(dfg::NavAbilityDFG, label::Symbol) + +getFactor(dfg::NavAbilityDFG, label::Symbol) + +getBlobentry(dfg::NavAbilityDFG, variableLabel::Symbol, label::Symbol) + +getVariableBlobentry(dfg::NavAbilityDFG, variableLabel::Symbol, label::Symbol) + +getFactorBlobentry(dfg::NavAbilityDFG, factorLabel::Symbol, label::Symbol) + +getGraphBlobentry(dfg::NavAbilityDFG, label::Symbol) + +getAgentBlobentry(dfg::NavAbilityDFG, label::Symbol) + +getVariableState(dfg::NavAbilityDFG, variableLabel::Symbol, label::Symbol) + +getFactorState(dfg::NavAbilityDFG, factorLabel::Symbol) + +getBlob(store::NavAbilityBlobstore, blobId::UUID) + +### Plural `get` + +### Singular `add` + +addBlob!(store::NavAbilityBlobstore, blobId::UUID, blob::Vector{UInt8}) + + +### Plural `add` + +### Singular `update` + +### Plural `update` + +### Singular `delete` + +### Plural `delete` + +### `list` \ No newline at end of file diff --git a/src/services/BlobEntry.jl b/src/services/BlobEntry.jl index a15b079..a11c4ab 100644 --- a/src/services/BlobEntry.jl +++ b/src/services/BlobEntry.jl @@ -97,6 +97,16 @@ function DFG.deleteAgentBlobEntry!(fgclient::NavAbilityDFG, entry::BlobEntry) return entry end +function DFG.deleteGraphBlobEntry!(fgclient::NavAbilityDFG, entry::BlobEntry) + response = executeGql( + fgclient, + GQL_DELETE_BLOBENTRY, + (id = getId(fgclient.fg, entry.label),), + ) + #TOOD check response.data["deleteBlobEntry"]["nodesDeleted"] + return entry +end + # ========================================================================================= # BlobEntry CRUD on other nodes # ========================================================================================= diff --git a/src/services/BlobStore.jl b/src/services/BlobStore.jl index d4bdb76..dfb75db 100644 --- a/src/services/BlobStore.jl +++ b/src/services/BlobStore.jl @@ -180,6 +180,7 @@ function DFG.addBlob!( filepath::AbstractString, blobId::UUID = uuid4(); chunkSize::Integer = UPLOAD_CHUNK_SIZE_HASH, + mimeType::String = "application/octet-stream", ) # locate large file on fs, ready to read in chunks fid = open(filepath,"r") @@ -195,7 +196,8 @@ function DFG.addBlob!( # custom header for pushing the file up headers_ = [ - # "Content-Length" => filesize, + "Content-Length" => filesize(filepath), + "Content-Type" => mimeType, "Accept" => "application/json, text/plain, */*", "Accept-Encoding" => "gzip, deflate, br", "Sec-Fetch-Dest" => "empty", @@ -241,14 +243,22 @@ function DFG.addBlob!( blobId end +function getMimetype(io::IO) + getFormat(s::DFG.FileIO.Stream{T}) where T = T + stream = DFG.FileIO.query(io) + # not sure if we need restrict to only our mimetypes, but better than nothing + mime = findfirst(==(getFormat(stream)), DFG._MIMETypes) + if isnothing(mime) + return MIME("application/octet-stream") + else + return mime + end +end -function DFG.addBlob!( - store::NavAbilityBlobStore, - blobId::UUID, - blob::Vector{UInt8}, -) +function DFG.addBlob!(store::NavAbilityBlobStore, blobId::UUID, blob::Vector{UInt8}) client = store.client + mimeType = getMimetype(IOBuffer(blob)) filesize = length(blob) # TODO: Use about a 50M file part here. np = 1 # TODO: ceil(filesize / 50e6) @@ -261,6 +271,7 @@ function DFG.addBlob!( # custom header for pushing the file up headers = [ "Content-Length" => filesize, + "Content-Type" => string(mimeType), "Accept" => "application/json, text/plain, */*", "Accept-Encoding" => "gzip, deflate, br", "Sec-Fetch-Dest" => "empty",