https://github.com/digitalruby/s3objectstore
Allow storing json objects in S3 easily
https://github.com/digitalruby/s3objectstore
Last synced: 7 months ago
JSON representation
Allow storing json objects in S3 easily
- Host: GitHub
- URL: https://github.com/digitalruby/s3objectstore
- Owner: DigitalRuby
- License: mit
- Created: 2022-06-27T17:39:27.000Z (over 3 years ago)
- Default Branch: main
- Last Pushed: 2024-03-24T01:25:18.000Z (almost 2 years ago)
- Last Synced: 2025-05-30T22:47:41.956Z (8 months ago)
- Language: C#
- Size: 86.9 KB
- Stars: 1
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# S3 Object Store
## Allow storing json objects in S3 easily
Goals:
- Map objects to a sensible s3 hierarchy
- Use json for fast-ish and flexible serialization and model updates + human readability
- Control the folder template name with options
Please see the Sandbox project, `Program.cs` which shows a simple example of using sessions.
### Usage
#### Define an object that implements the `IStorageObject` interface:
```cs
///
/// Example session object
///
public sealed class Session : IStorageObject
{
///
/// The session identifier, probably a guid
///
[JsonPropertyName("k")]
public string? Key { get; set; } = string.Empty;
///
/// The account id the session belongs to, probably a guid. Can be null if no owner.
///
[JsonPropertyName("o")]
public string? Owner { get; set; }
///
/// IP address
///
[JsonPropertyName("i")]
public string IPAddress { get; set; } = string.Empty;
///
/// User agent
///
[JsonPropertyName("a")]
public string UserAgent { get; set; } = string.Empty;
///
/// When the session expires
///
[JsonPropertyName("e")]
public DateTimeOffset Expires { get; set; }
///
/// Could put permissions for the session here
///
[JsonPropertyName("p")]
public string Permissions { get; set; } = string.Empty;
///
public override string ToString()
{
return $"{Key} {Owner} {IPAddress} {UserAgent} {Expires} {Permissions}";
}
}
```
Using `JsonPropertyName` to shorten property names is highly recommended as it will save you on storage space.
The `IStorageObject` interface will return null for both `Key` and `Owner` by default.
In most cases, you will usually implement both the `Key` and `Owner` properties yourself and return `Guid` or some other identifier.
Exceptions to this case:
- You can return null for the `Owner` if your service options (see down below) do not have a format specifier for the owner in the folder template - `{0}`.
- You can return null for the `Key` if your service options specify that the folder format has the file name in it. By default, the `Key` is used as the file name, with a `.json` extension.
#### Create your s3 repository
```cs
// note disable signing is required for cloudflare r2
// set disable signing to false as long as your s3 provider works
var config = new S3Config(accessKey, secretKey, url, disableSigning);
// in production, deleting and creating buckets is not allowed for safety
// you can get both the environment and logger from `IServiceProvider` when using a full .net 6 app.
var repository = new S3StorageRepository(config, new FakeEnvironment(), new NullLogger());
```
#### Create your object service
```cs
var serviceOptions = new StorageObjectServiceOptions
{
Bucket = "bucketname",
// the folder format does not need a {0} if there is no owner for the object (owner is null)
// by default the key will be appended to this folder with a .json extension
FolderFormat = "users/{0}/sessions",
// if your folder format contains the file name, for example to store a user profile, you could use:
// users/{0}/profile.json, which would ignore the key as part of the file name
FolderFormatIncludesFileName = false
};
// create s3 object service, wrapping the s3 repository
var service = new S3StorageObjectService(serviceOptions, repository);
```
#### Perform operations
The storage object service interface is as follows:
```cs
///
/// Storage object service interface. Stores one or more objects (like sessions) with an owner (like a user).
///
/// Types of objects to work with, must be json serializable
public interface IStorageObjectService where T : class, IStorageObject
{
///
/// Get an object by key and owner
///
/// Key
/// Owner identifier
/// Object or null if not found
Task GetObjectAsync(string key, string owner);
///
/// Set an object. The key and owner properties are used to determine the folder path
///
/// Object
/// Task
Task SetObjectAsync(T obj);
///
/// Get all objects for the owner.
///
/// Owner identifier
/// Task of found objects
Task> GetObjectsAsync(string owner);
///
/// Get just the keys for the owner, much more lightweight operation
///
/// Owner
/// Task of keys
Task> GetKeys(string owner);
///
/// Delete object.
///
/// Key
/// Owner identifier
/// Task
Task DeleteObjectAsync(string key, string owner);
}
```
Please email support@digitalruby.com if you have questions or feedback.
-- Jeff