github.com/ipld/go-ipld-prime@v0.21.0/storage/doc.go (about) 1 // The storage package contains interfaces for storage systems, and functions for using them. 2 // 3 // These are very low-level storage primitives. 4 // The interfaces here deal only with raw keys and raw binary blob values. 5 // 6 // In IPLD, you can often avoid dealing with storage directly yourself, 7 // and instead use linking.LinkSystem to handle serialization, hashing, and storage all at once. 8 // (You'll hand some values that match interfaces from this package to LinkSystem when configuring it.) 9 // It's probably best to work at that level and above as much as possible. 10 // If you do need to interact with storage more directly, the read on. 11 // 12 // The most basic APIs are ReadableStorage and WritableStorage. 13 // When writing code that works with storage systems, these two interfaces should be seen in almost all situations: 14 // user code is recommended to think in terms of these types; 15 // functions provided by this package will accept parameters of these types and work on them; 16 // implementations are expected to provide these types first; 17 // and any new library code is recommended to keep with the theme: use these interfaces preferentially. 18 // 19 // Users should decide which actions they want to take using a storage system, 20 // find the appropriate function in this package (n.b., package function -- not a method on an interface! 21 // You will likely find one of each, with the same name: pick the package function!), 22 // and use that function, providing it the storage system (e.g. either ReadableStorage, WritableStorage, or sometimes just Storage) 23 // as a parameter. 24 // That function will then use feature-detection (checking for matches to the other, 25 // more advanced and more specific interfaces in this package) and choose the best way 26 // to satisfy the request; or, if it can't feature-detect any relevant features, 27 // the function will fall back to synthesizing the requested behavior out of the most basic API. 28 // Using the package functions, and letting them do the feature detection for you, 29 // should provide the most consistent user experience and minimize the amount of work you need to do. 30 // (Bonus: It also gives us a convenient place to smooth out any future library migrations for you!) 31 // 32 // If writing new APIs that are meant to work reusably for any storage implementation: 33 // APIs should usually be designed around accepting ReadableStorage or WritableStorage as parameters 34 // (depending on which direction of data flow the API is regarding). 35 // and use the other interfaces (e.g. StreamingReadableStorage) thereafter internally for feature detection. 36 // For APIs which may sometimes be found relating to either a read or a write direction of data flow, 37 // the Storage interface may be used in order to define a function that should accept either ReadableStorage or WritableStorage. 38 // In other words: when writing reusable APIs, one should follow the same pattern as this package's own functions do. 39 // 40 // Similarly, implementers of storage systems should always implement either ReadableStorage or WritableStorage first. 41 // Only after satisfying one of those should the implementation then move on to further supporting 42 // additional interfaces in this package (all of which are meant to support feature-detection). 43 // Beyond one of the basic two, all the other interfaces are optional: 44 // you can implement them if you want to advertise additional features, 45 // or advertise fastpaths that your storage system supports; 46 // but you don't have implement any of those additional interfaces if you don't want to, 47 // or if your implementation can't offer useful fastpaths for them. 48 // 49 // Storage systems as described by this package are allowed to make some interesting trades. 50 // Generally, write operations are allowed to be first-write-wins. 51 // Furthermore, there is no requirement that the system return an error if a subsequent write to the same key has different content. 52 // These rules are reasonable for a content-addressed storage system, and allow great optimizations to be made. 53 // 54 // Note that all of the interfaces in this package only use types that are present in the golang standard library. 55 // This is intentional, and was done very carefully. 56 // If implementing a storage system, you should find it possible to do so *without* importing this package. 57 // Because only standard library types are present in the interface contracts, 58 // it's possible to implement types that align with the interfaces without refering to them. 59 // 60 // Note that where keys are discussed in this package, they use the golang string type -- 61 // however, they may be binary. (The golang string type allows arbitrary bytes in general, 62 // and here, we both use that, and explicitly disavow the usual "norm" that the string type implies UTF-8. 63 // This is roughly the same as the practical truth that appears when using e.g. os.OpenFile and other similar functions.) 64 // If you are creating a storage implementation where the underlying medium does not support arbitrary binary keys, 65 // then it is strongly recommend that your storage implementation should support being configured with 66 // an "escaping function", which should typically simply be of the form `func(string) string`. 67 // Additional, your storage implementation's documentation should also clearly describe its internal limitations, 68 // so that users have enough information to write an escaping function which 69 // maps their domain into the domain your storage implementation can handle. 70 package storage 71 72 // also note: 73 // LinkContext stays *out* of this package. It's a chooser-related thing. 74 // LinkSystem can think about it (and your callbacks over there can think about it), and that's the end of its road. 75 // (Future: probably LinkSystem should have SetStorage and SetupStorageChooser methods for helping you set things up -- where the former doesn't discuss LinkContext at all.)