text:
# Resource Hooks
This section covers the usage of **Resource Hooks**, which is a feature of`ResourceDefinition<T>`. See the [ResourceDefinition usage guide](resource-definitions.md) for a general explanation on how to set up a `ResourceDefinition<T>`. For a quick start, jump right to the [Getting started: most minimal example](#getting-started-most-minimal-example) section.

By implementing resource hooks on a `ResourceDefintion<T>`, it is possible to intercept the execution of the **Resource Service Layer** (RSL) in various ways. This enables the developer to conveniently define business logic without having to override the RSL. It can be used to implement e.g.
* Authorization
* [Event-based synchronisation between microservices](https://docs.microsoft.com/en-us/dotnet/standard/microservices-architecture/multi-container-microservice-net-applications/integration-event-based-microservice-communications)
* Logging
* Transformation of the served data

This usage guide covers the following sections
1.  [**Semantics: pipelines, actions and hooks**](#semantics-pipelines-actions-and-hooks)
Understanding the semantics will be helpful in identifying which hooks on `ResourceDefinition<T>` you need to implement for your use-case.
2.  [**Basic usage**](#basic-usage)
        Some examples to get you started.
      * [**Getting started: most minimal example**](#getting-started-most-minimal-example)
      * [**Logging**](#logging)
      * [**Transforming data with OnReturn**](#transforming-data-with-onreturn)
      * [**Loading database values**](#loading-database-values)
3.  [**Advanced usage**](#advanced-usage)
    Complicated examples that show the advanced features of hooks.
      * [**Simple authorization: explicitly affected resources**](#simple-authorization-explicitly-affected-resources)
      * [**Advanced authorization: implicitly affected resources**](#advanced-authorization-implicitly-affected-resources)
      * [**Synchronizing data across microservices**](#synchronizing-data-across-microservices)
      * [**Hooks for many-to-many join tables**](#hooks-for-many-to-many-join-tables)
5.  [**Hook execution overview**](#hook-execution-overview)
  A table overview of all pipelines and involved hooks

# 1. Semantics: pipelines, actions and hooks

## Pipelines
The different execution flows within the RSL that may be intercepted can be identified as **pipelines**. Examples of such pipelines are
* **Post**: creation of a resource (triggered by the endpoint `POST /my-resource`).
* **PostBulk**: creation of multiple resources (triggered by the endpoint `POST /bulk/my-resource`).
  * *NB: hooks are not yet supported with bulk operations.*
* **Get**: reading a resource (triggered by the endpoint `GET /my-resource`).
* **GetSingle**: reading a single resource (triggered by the endpoint `GET /my-resource/1`).

See the [ResourcePipeline](https://github.com/json-api-dotnet/JsonApiDotNetCore/blob/feat/%23477/src/JsonApiDotNetCore/Hooks/Execution/ResourcePipelineEnum.cs) enum for a full list of available pipelines.

## Actions
Each pipeline is associated with a set of **actions** that work on resources and their relationships. These actions reflect the associated database operations that is performed by JsonApiDotNetCore (in the Repository Layer). Typically, the RSL will execute some service-layer-related code, then invoke the Repository Layer which will perform these actions, after which the execution returns to the RSL.

Note that some actions are shared across different pipelines, and note that most pipelines perform multiple actions.  There are two types of actions: **main resource actions** and **nested resource actions**.

### Main resource actions
Most actions are trivial in the context of the pipeline where they're executed from. They may be recognised as the familiar *CRUD* operations of an API. These actions are:

* The `create` action: the **Post** pipeline will `create` a resource
* The `read` action: the **Get** and  **GetSingle** pipeline will `read` (a) resource(s).
* The `update` action: the **Patch** pipeline will `update` a resource.
* The `delete` action: the **Delete** pipeline will `delete` a resource.

These actions are called the **main resource actions** of a particular pipeline because **they act on the request resource**. For example, when an `Article` is created through the **Post** pipeline, its main action, `create`, will work on that `Article`.

### Nested Resource Actions
Some other actions might be overlooked, namely the nested resource actions. These actions are

*  `update relationship`  for directly affected relationships
*  `implicit update relationship` for implicitly affected relationships
* `read` for included relationships

These actions are called **nested resource actions** of a particular pipeline because **they act on involved (nested) resources** instead of the main request resource. For example, when loading articles and their respective authors (`GET /articles?include=author`), the `read` action on `Article` is the main action, and the `read` action on `Person` is the nested action.

**The `update relationship` action**
[As per the Json:Api specification](https://jsonapi.org/format/#crud-creating](https://jsonapi.org/format/#crud-creating), the **Post** pipeline also allows for an `update relationship` action on an already existing resource. For example, when creating an `Article` it is possible to simultaneously relate it to an existing `Person` by setting its author. In this case, the `update relationship` action is a nested action that will work on that `Person`.

**The `implicit update relationship` action**
the **Delete**  pipeline also allows for an `implicit update relationship` action on an already existing resource. For example, for an  `Article` that its author property assigned to a particular `Person`,  the relationship between them is destroyed when this article is deleted. This update is "implicit" in the sense that no explicit information about that `Person` was provided in the request that triggered this pipeline. An `implicit update relationship` action is therefore performed on that `Person`.  See [this section](#advanced-authorization-implicitly-affected-resources) for a more detailed.

### Shared actions
Note that **some actions are shared across pipelines**. For example, both the **Post** and **Patch** pipeline can perform the `update relationship`  action on an (already existing) involved resource. Similarly, the **Get** and **GetSingle** pipelines perform the same `read` action.

For a complete list of actions associated with each pipeline, see the [overview table](#hook-execution-overview).

## Hooks
For all actions it is possible to implement **at least one hook** to intercept its execution. These hooks can be implemented by overriding the corresponding virtual  implementation on `ResourceDefintion<T>`. (Note that the base implementation is a dummy implementation, which is ignored when firing hooks.)

### Action related hooks
As an example, consider the `create` action for the `Article` Resource. This action can be intercepted by overriding the
*  `ResourceDefintion<Article>.BeforeCreate` hook for custom logic **just before** execution of the main `create` action
* `ResourceDefintion<Article>.AfterCreate` hook for custom logic **just after** execution of the main `create` action

If with the creation of an `Article`  a relationship to `Person` is updated simultaneously, this can be intercepted by overriding the
* `ResourceDefintion<Person>.BeforeUpdateRelationship` hook for custom logic **just before** the execution of the nested `update relationship` action.
* `ResourceDefintion<Person>.AfterUpdateRelationship` hook for custom logic **just after** the execution of the nested `update relationship` action.

### OnReturn hook
As mentioned in the previous section, some actions are shared across hooks. One of these actions is the `return` action. Although not strictly compatible with the *CRUD* vocabulary, and although not executed by the Repository Layer, pipelines are also said to perform a `return` action when any content is to be returned from the API. For example, the **Delete** pipeline does not return any content, but a *HTTP 204 No Content* instead, and will therefore not perform a `return` action. On the contrary, the **Get** pipeline does return content, and will therefore perform a `return action`

Any return content can be intercepted and transformed as desired by implementing the `ResourceDefintion<TEntity>.OnReturn` hook which intercepts the `return` action. For this action, there is no distinction between a `Before` and `After` hook, because no code after a `return` statement can be evaluated. Note that the `return` action can work on *main resources as well as nested resources*, see  [this example below](#transforming-data-with-onreturn).

For an overview of all pipelines, hooks and actions, see the table below, and for more detailed information about the available hooks, see the [IResourceHookContainer<T>](https://github.com/json-api-dotnet/JsonApiDotNetCore/blob/ab1f96d8255532461da47d290c5440b9e7e6a4a5/src/JsonApiDotNetCore/Hooks/IResourceHookContainer.cs) interface.

# 2. Basic usage

## Getting started: most minimal example
To use resource hooks, you are required to turn them on in your `startup.cs` configuration

```c#
public void ConfigureServices(IServiceCollection services)
{
    ...
    services.AddJsonApi<ApiDbContext>(
        options =>
        {
            options.EnableResourceHooks = true; // default is false
            options.LoadDatabaseValues = false; // default is false
        }
    );
    ...
}
```
For this example, we may set `LoadDatabaseValues` to `false`. See the [Loading database values](#loading-database-values) example for more information about this option.

The simplest case of resource hooks we can then implement should not require a lot of explanation.  This hook would triggered by any default JsonApiDotNetCore API route for `Article`.
```c#
public class ArticleResource : ResourceDefinition<Article>
{
    public override IEnumerable<Article> OnReturn(HashSet<Article> entities, ResourcePipeline pipeline)
    {
        Console.WriteLine("This hook does not do much apart from writing this message" +
             " to the console just before serving the content");
        return entities;
    }
}
```
## Logging
This example shows how some actions can be logged on the level of API users.

First consider the following scoped service which creates a logger bound to a particular user and request.
```c#
/// This is a scoped service, which means wil log will have a request-based
/// unique id associated to it.
public class UserActionsLogger : IUserActionsLogger
{
    public ILogger Instance { get; private set; }
    public UserActionsLogger(ILoggerFactory loggerFactory,
                             IUserService userService)
    {
        var userId = userService.GetUser().Id;
        Instance = loggerFactory.CreateLogger($"[request: {Guid.NewGuid()}"
        + "user: {userId}]");
    }
}
```
Now, let's assume our application has two resources: `Article` and `Person`, and that there exist a one-to-one  and one-to-many relationship between them (`Article has one Author` and `Article has many Reviewers`). Let's assume we are required to log the following events
* An API user deletes an article
* An API user removes the `Author` relationship of a person
* An API user removes the `Reviewer` relationship of a person

This could be achieved in the following way
```c#
/// Note that resource definitions are also registered as scoped services.
public class ArticleResource : ResourceDefinition<Article>
{
    private readonly ILogger _userLogger;
    public ArticleResource(IUserActionsLogger logService)
    {
        _userLogger = logService.Instance;
    }

    public override void AfterDelete(HashSet<Article> entities, ResourcePipeline pipeline, bool succeeded)
    {
        if (!succeeded) return
        foreach (Article a in entities)
        {
            _userLogger.Log(LogLevel.Information, $"Deleted article '{a.Name}' with id {a.Id}");
        }
    }
}

public class PersonResource : ResourceDefinition<Person>
{
    private readonly ILogger _userLogger;
    public PersonResource(IUserActionsLogger logService)
    {
        _userLogger = logService.Instance;
    }

    public override void AfterUpdateRelationship(IAffectedRelationships<Person> resourcesByRelationship, ResourcePipeline pipeline)
    {
      var updatedRelationshipsToArticle = relationshipHelper.EntitiesRelatedTo<Article>();
        foreach (var updated in updatedRelationshipsToArticle)
        {
            RelationshipAttribute relationship = updated.Key;
            HashSet<Person> affectedEntities = updated.Value;

            foreach (Person p in affectedEntities)
            {
                if (pipeline == ResourcePipeline.Delete)
                {
                    _userLogger.Log(LogLevel.Information, $"Deleted the {relationship.PublicRelationshipName}" +
                    "relationship to Article for person '{p.FirstName + p.LastName}' with {p.Id}");
                }
            }
        }
    }
}
```

If eg. a API user deletes an article with title *JSON:API paints my bikeshed!* that had related as author *John* and as reviewer *Frank*, the logs generated logs would look something like

```
[request: 186190e3-1900-4329-9181-42082258e7b4, user: dd1cd99d-60e9-45ca-8d03-a0330b07bdec] Deleted article 'JSON:API paints my bikeshed!' with id fac0436b-7aa5-488e-9de7-dbe00ff8f04d
[request: 186190e3-1900-4329-9181-42082258e7b4, user: dd1cd99d-60e9-45ca-8d03-a0330b07bdec] Deleted the author relationship to Article for person 'John' with id 2ec3990d-c816-4d6d-8531-7da4a030d4d0
[request: 186190e3-1900-4329-9181-42082258e7b4, user: dd1cd99d-60e9-45ca-8d03-a0330b07bdec] Deleted the reviewer relationship to Article for person 'Frank' with id 42ad6eb2-b813-4261-8fc1-0db1233e665f
```
## Transforming data with OnReturn
Using the `OnReturn` hook, any set of resources can be manipulated as desired before serving it from the API. One of the use-cases for this is being able to perform a [filtered included](https://github.com/aspnet/EntityFrameworkCore/issues/1833), which is currently not supported by Entity Framework Core.

As an example, consider again an application with the `Article`  and `Person` resource, and let's assume the following business rules
* when reading `Article`s, we never want to show articles for which the `SoftDeleted` property is set to true.
* when reading `Person`s, we never want to show people who wish to remain anonymous (`Anonymous` is set to true).

This can be achieved as follows.

```c#
public class ArticleResource : ResourceDefinition<Article>
{
    public override IEnumerable<Article> OnReturn(HashSet<Article> entities, ResourcePipeline pipeline)
    {
        return entities.Where(a => a.SoftDeleted == false);
    }
}

public class PersonResource : ResourceDefinition<Person>
{
    public override IEnumerable<Person> OnReturn(HashSet<Person> entities, ResourcePipeline pipeline)
    {
        if (pipeline == ResourcePipeline.Get)
        {
            return entities.Where(p => p.Anonymous == false);
        }
        return entities;
    }
}
```
Note that not only anonymous people will be excluded when directly performing a `GET /people`, but also when included through relationships, like `GET /articles?include=author,reviewers`. Simultaneously, `if` condition that checks for `ResourcePipeline.Get` in the `PersonResource` ensures we still get expected responses from the API when eg. creating a person with `WantsPrivacy` set to true.

## Loading database values
When a hook is executed for a particular resource, JsonApiDotNetCore can load the corresponding database values and provide them in the hooks. This can be useful for eg.
 * having a diff between a previous and new state of a resource (for example when updating a resource)
 * performing authorization rules based on the property of a resource.

For example, consider a scenario in with the following two requirements:
* We need to log all updates on resources revealing their old and new value.
* We need to check if the property `IsLocked` is set is `true`, and if so, cancel the operation.

 Consider an `Article` with title *Hello there* and API user trying to update the the title of this article to *Bye bye*.  The above requirements could be implemented as follows
```c#
public class ArticleResource : ResourceDefinition<Article>
{
    private readonly ILogger _logger;
    private readonly IJsonApiContext _context;
    public constructor ArticleResource(ILogger logger, IJsonApiContext context)
    {
        _logger = logger;
        _context = context;
    }

    public override IEnumerable<Article> BeforeUpdate(IResourceDiff<Article> entityDiff, ResourcePipeline pipeline)
    {
        // PropertyGetter is a helper class that takes care of accessing the values on an instance of Article using reflection.
        var getter = new PropertyGetter<Article>();

        // ResourceDiff<T> is a class that is like a list that contains ResourceDiffPair<T> elements
        foreach (ResourceDiffPair<Article> affected in entityDiff)
        {
            var currentDatabaseState = affected.DatabaseValue; // the current state in the database
            var proposedValueFromRequest = affected.Entity; // the value from the request

            if (currentDatabaseState.IsLocked) throw new JsonApiException(403, "Forbidden: this article is locked!")

             foreach (var attr in _context.AttributesToUpdate)
            {
                var oldValue = getter(currentDatabaseState, attr);
                var newValue = getter(proposedValueFromRequest, attr);

                _logger.LogAttributeUpdate(oldValue, newValue)
            }
        }
        // You must return IEnumerable<Article> from this hook.
        // This means that you could reduce the set of entities that is
        // affected by this request, eg. by entityDiff.Entities.Where( ... );
        entityDiff.Entities;
    }
}
```
In this case the `ResourceDiffPair<T>.DatabaseValue` is `null`.  If you try to access all database values at once (`ResourceDiff.DatabaseValues`) when it they are turned off, an exception will be thrown.

Note that database values are turned on by default. They can be turned of globally by configuring the startup as follows:
```c#
public void ConfigureServices(IServiceCollection services)
{
    ...
    services.AddJsonApi<ApiDbContext>(
        options =>
        {
            options.LoadDatabaseValues = false; // default is false
        }
    );
    ...
}
```

The global setting can be used together with per-hook configuration hooks using the `LoadDatabaseValues` attribute:
```c#
public class ArticleResource : ResourceDefinition<Article>
{
  [LoadDatabaseValues(true)]
    public override IEnumerable<Article> BeforeUpdate(IResourceDiff<Article> entityDiff, ResourcePipeline pipeline)
    {
      ....
    }

  [LoadDatabaseValues(false)]
    public override IEnumerable<string> BeforeUpdateRelationships(HashSet<string>  ids,  IAffectedRelationships<Article>  resourcesByRelationship,  ResourcePipeline  pipeline)
    {
      // the entities stored in the IAffectedRelationships<Article> instance
      // are plain resource identifier objects when LoadDatabaseValues is turned off,
      // or objects loaded from the database when LoadDatabaseValues is turned on.
     ....
     }
  }
}
```

Note that there are some hooks that the  `LoadDatabaseValues` option and attribute does not affect. The only hooks that are affected are:
* `BeforeUpdate`
* `BeforeUpdateRelationship`
*  `BeforeDelete`

# 3. Advanced usage

## Simple authorization: explicitly affected resources
Resource hooks can be used to easily implement authorization in your application.  As an example, consider the case in which an API user is not allowed to see anonymous people, which is reflected by the `Anonymous` property on `Person`  being set to true`true`.  The API should handle this as follows:
* When reading people (`GET /people`), it should hide all people that are set to anonymous.
* When reading a single person (`GET /people/{id}`), it should throw an authorization error if the particular requested person is set to anonymous.

This can be achieved as follows:
```c#
public class PersonResource : ResourceDefinition<Person>
{
  private readonly _IAuthorizationHelper _auth;
    public constructor PersonResource(IAuthorizationHelper auth)
    {
      // IAuthorizationHelper is a helper service that handles all authorization related logic.
      _auth = auth;
    }

    public override IEnumerable<Person> OnReturn(HashSet<Person> entities, ResourcePipeline pipeline)
    {
    if (!_auth.CanSeeSecretPeople())
    {
       if (pipeline == ResourcePipeline.GetSingle)
       {
         throw new JsonApiException(403, "Forbidden to view this person", new  UnauthorizedAccessException());
       }
       entities = entities.Where( p => !p.IsSecret)
    }
    return entities;
    }
}
```
This example of authorization is considered simple because it only involves one resource. The next example shows a more complex case

## Advanced authorization: implicitly affected resources
Let's consider an authorization scenario for which we are required to implement multiple hooks across multiple resource definitions. We will assume the following:
* There exists a one-to-one relationship between `Article` and `Person`: an article can have only one author, and a person can be author of only one article.
* The author of article `Old Article` is person `Alice`.
* The author of article `New Article` is person `Bob`.

Now let's consider an API user that tries to update `New Article` by setting its author to `Alice`. The request would look something like `PATCH /articles/{NewArticleId}` with a body containing a reference to `Alice`.

First to all, we wish to authorize this operation by the verifying permissions related to the resources that are **explicity affected**  by it:
1. Is the API user allowed to update `New Article`?
2. Is the API user allowed to update `Alice`?

Apart from this, we also wish to verify permissions for the resources that are **implicitly affected** by this operation: `Bob` and `Old Article`. Setting `Alice` as the new author of `New Article` will result in removing the following two relationships:  `Bob` being an author of `New Article`, and `Alice` being an author of  `Old Article`. Therefore, we wish wish to verify the related permissions:

3. Is the API user allowed to update `Bob`?
4. Is the API user allowed to update `Old Article`?

This authorization requirement can be fulfilled as follows.

For checking the permissions for the explicitly affected resources, `New Article` and `Alice`, we may implement the `BeforeUpdate` hook for `Article`:
```c#
public override IEnumerable<Article> BeforeUpdate(IResourceDiff<Article> entityDiff, ResourcePipeline pipeline)
{
    if (pipeline == ResourcePipeline.Patch)
    {
        Article a = entityDiff.RequestEntities.Single();
        if (!_auth.CanEditResource(a))
        {
            throw new JsonApiException(403, "Forbidden to update properties of this article", new UnauthorizedAccessException());
        }
        if (entityDiff.GetByRelationship<Person>().Any() && _auth.CanEditRelationship<Person>(a))
        {
            throw new JsonApiException(403, "Forbidden to update relationship of this article", new UnauthorizedAccessException());
        }
    }
    return entityDiff.RequestEntities;
}
```

 and the `BeforeUpdateRelationship` hook for `Person`:
```c#
public override IEnumerable<string> BeforeUpdateRelationship(HashSet<string> ids, IAffectedRelationships<Person> resourcesByRelationship, ResourcePipeline pipeline)
{
    var updatedOwnerships = resourcesByRelationship.GetByRelationship<Article>();
    if (updatedOwnerships.Any())
    {
        Person p = resourcesByRelationship.GetByRelationship<Article>().Single().Value.First();
        if (_auth.CanEditRelationship<Article>(p))
        {
            throw new JsonApiException(403, "Forbidden to update relationship of this person", new UnauthorizedAccessException());
        }
    }
    return ids;
}
```

To verify the permissions for the implicitly affected resources, `Old Article` and `Bob`, we need to implement the `BeforeImplicitUpdateRelationship` hook for `Article`:
```c#
public override void BeforeImplicitUpdateRelationship(IAffectedRelationships<Article> resourcesByRelationship, ResourcePipeline pipeline)
{
    var updatedOwnerships = resourcesByRelationship.GetByRelationship<Person>();
    if (updatedOwnerships.Any())
    {
        Article a = resourcesByRelationship.GetByRelationship<Person>().Single().Value.First();
        if (_auth.CanEditRelationship<Person>(a))
        {
            throw new JsonApiException(403, "Forbidden to update relationship of this article", new UnauthorizedAccessException());
        }
    }
}
```
and similarly for `Person`:
```c#
public override void BeforeImplicitUpdateRelationship(IAffectedRelationships<Person> resourcesByRelationship, ResourcePipeline pipeline)
{
    var updatedOwnerships = resourcesByRelationship.GetByRelationship<Article>();
    if (updatedOwnerships.Any())
    {
        Person p = resourcesByRelationship.GetByRelationship<Article>().Single().Value.First();
        if (_auth.CanEditRelationship<Article>(p))
        {
            throw new JsonApiException(403, "Forbidden to update relationship of this article", new UnauthorizedAccessException());
        }
    }
}
```

## Using Resource Hooks without Entity Framework Core

If you want to use Resource Hooks without Entity Framework Core, there are several things that you need to consider that need to be met. For any resource that you want to use hooks for:
1. The corresponding resource repository must fully implement `IResourceReadRepository<TEntity, TId>`
2. If you are using custom services, you will be responsible for injecting the `IResourceHookExecutor` service into your services and call the appropriate methods. See the [hook execution overview](#hook-execution-overview) to determine which hook should be fired in which scenario.

If you are required to use the `BeforeImplicitUpdateRelationship` hook (see previous example), there is an additional requirement. For this hook, given a particular relationship, JsonApiDotNetCore needs to be able to resolve the inverse relationship. For example: if `Article` has one  author (a `Person`), then it needs to be able to resolve the `RelationshipAttribute` that corresponds to the inverse relationship for the `author` property. There are two approaches :

1. **Tell JsonApiDotNetCore how to do this only for the relevant models**.  If you're using the `BeforeImplicitUpdateRelationship` hook only for a small set of models, eg only for the relationship of the example, then it is easiest to provide the `inverseNavigationProperty` as follows:
```c#
public class Article : Identifiable
{
    ...
    [HasOne("author", inverseNavigationProperty: "OwnerOfArticle")]
    public Person Author { get; set; }
    ...
}
public class Person : Identifiable
{
    ...
    [HasOne("article")]
    public Article OwnerOfArticle { get; set; }
    ...
}
```
2. **Tell JsonApiDotNetCore how to do this in general**. For full support, you can provide JsonApiDotNetCore with a custom service implementation of the `IInverseRelationships` interface. relationship of the example, then it is easiest to provide the `inverseNavigationProperty` as follows:
```c#
public class CustomInverseRelationshipsResolver : IInverseRelationships
{
    public void Resolve()
    {
        // the implementation of this method depends completely
        // the data access layer you're using.
        // It should set the RelationshipAttribute.InverseRelationship property
        // for all (relevant) relationships.
        // To have an idea of how to implement this method, see the InverseRelationships class
        // in the source code of JsonApiDotNetCore:
        // https://github.com/json-api-dotnet/JsonApiDotNetCore/blob/59a93590ac4f05c9c246eca9459b49e331250805/src/JsonApiDotNetCore/Internal/InverseRelationships.cs
    }
}
```
This  service will then be called run once at startup and take care of the metadata that is required for `BeforeImplicitUpdateRelationship` to be supported.

*Note: don't forget to register this singleton service with the service provider.*

## Synchronizing data across microservices
If your application is built using a microservices infrastructure, it may be relevant to propagate data changes between microservices, [see this article for more information](https://docs.microsoft.com/en-us/dotnet/standard/microservices-architecture/multi-container-microservice-net-applications/integration-event-based-microservice-communications). In this example, we will assume the implementation of an event bus and we will publish data consistency integration events using resource hooks.

```c#
public class ArticleResource : ResourceDefinition<Article>
{
    private readonly IEventBus _bus;
    private readonly IJsonApiContext _context;
    public ArticleResource(IEventBus bus, IJsonApiContext context)
    {
        _bus = bus;
        _context = context;
    }
    public override void AfterCreate(HashSet<Article> entities, ResourcePipeline pipeline)
    {
        foreach (var article in entities )
        {
            var @event = new ResourceCreatedEvent(article);
            _bus.Publish(@event);
        }
    }

    public override void AfterDelete(HashSet<Article> entities, ResourcePipeline pipeline, bool succeeded)
    {
        foreach (var article in entities)
        {
            var @event = new ResourceDeletedEvent(article);
            _bus.Publish(@event);
        }
    }

    public override void AfterUpdate(HashSet<Article> entities, ResourcePipeline pipeline)
    {
        foreach (var article in entities)
        {
          // You could inject IJsonApiContext and use it to pass along only the attributes that were updated
            var @event = new ResourceUpdatedEvent(article, properties: _context.AttributesToUpdate);
            _bus.Publish(@event);
        }
    }
}
```

## Hooks for many-to-many join tables
In this example we consider an application with a many-to-many relationships: `Article` and `Tag`, with an internally used `ArticleTag` throughtype.

Usually, join table records will not contain any extra information other than that which is used internally for the many-to-many relationship. For this example, the throughtype should then look like:
```c#
public class ArticleTag
{
    public int ArticleId { get; set; }
    public Article Article { get; set; }
    public int TagId { get; set; }
    public Tag Tag { get; set; }
}
```
If we then eg. implement the `AfterRead` and `OnReturn` hook for `Article` and `Tag`, and perform a `GET /articles?include=tags` request, we may expect the following order of execution:

1. Article AfterRead
2. Tag AfterRead
3. Article OnReturn
4. Tag OnReturn

Note that under the hood, the *join table records* (instances of `ArticleTag`) are also being read, but we did not implement any hooks for them. In this example, for these records, there is little relevant business logic that can be thought of.

Sometimes, however, relevant data may be stored in the join table of a many-to-many relationship. Let's imagine we wish to add a property `LinkDate` to the join table that reflects when a tag was added to an article. In this case, we may want to execute business logic related to these records: we may for example want to hide any tags that were added to an article longer than 2 weeks ago.

In order to achieve this, we need to change `ArticleTag` to `ArticleTagWithLinkDate` as follows:
```c#
public class ArticleTagWithLinkDate : Identifiable
{
    public int ArticleId { get; set; }
    [HasOne("Article")]
    public Article Article { get; set; }
    public int TagId { get; set; }
    [HasOne("Tag")]
    public Tag Tag { get; set; }
    public DateTime LinkDate { get; set; }
}
```
Then, we may implement a hook for `ArticleTagWithLinkDate` as usual:
```c#
public class ArticleTagWithLinkDateResource : ResourceDefinition<ArticleTagWithLinkDate>
{
    public override IEnumerable<ArticleTagWithLinkDate> OnReturn(HashSet<ArticleTagWithLinkDate> entities, ResourcePipeline pipeline)
    {
        return entities.Where(e => (DateTime.Now - e.LinkDate) < 14);
    }
}
```
Then, for the same request `GET /articles?include=tags`, the order of execution of the hooks will look like:
1. Article AfterRead
2. Tag AfterRead
3. Article OnReturn
4. ArticleTagWithLinkDate OnReturn
5. Tag OnReturn

And the included collection of tags per article will only contain tags that were added less than two weeks ago.

Note that the introduced inheritance and added relationship attributes does not further affect the many-to-many relationship internally.

# 4. Hook execution overview

This table below shows the involved hooks per pipeline.

    Pipeline
    Execution Flow

    Before Hooks
    Repository Actions
    After Hooks
    OnReturn

    Get
    BeforeRead
    read
    AfterRead
    [x]

    GetSingle
    BeforeRead
    AfterRead
    [x]

    GetRelationship
    BeforeRead
    AfterRead
    [x]

    Post
    BeforeCreate
    create
update relationship
    AfterCreate
    [x]

    Patch
    BeforeUpdate
BeforeUpdateRelationship
BeforeImplicitUpdateRelationship
    update
update relationship
implicit update relationship
    AfterUpdate
AfterUpdateRelationship
    [x]

    PatchRelationship
    BeforeUpdate
BeforeUpdateRelationship
    update
update relationship
implicit update relationship
    AfterUpdate
AfterUpdateRelationship
    [ ]

    Delete
    BeforeDelete
    delete
implicit update relationship
    AfterDelete
    [ ]

    BulkPost
    Not yet supported

    BulkPatch
    Not yet supported

    BulkDelete
    Not yet supported

repository: mrnkr/JsonApiDotNetCore

repo_name: mrnkr/JsonApiDotNetCore


text:
# Federating System and User metrics to Azure Files in Azure RedHat OpenShift

**Paul Czarkowski**

*06/04/2021*

By default Azure RedHat OpenShift (ARO) stores metrics in Ephemeral volumes, and its advised that users do not change this setting. However its not unreasonable to expect that metrics should be persisted for a set amount of time.

This guide shows how to set up Thanos to federate both System and User Workload Metrics to a Thanos gateway that stores the metrics in Azure Files and makes them available via a Grafana instance (managed by the Grafana Operator).

> ToDo - Add Authorization in front of Thanos APIs

## Pre-Prequsites

1. An ARO cluster

1. clone this repo down locally

    ```bash
    git clone https://github.com/rh-mobb/documentation
    cd docs/aro/federated-metrics
    ```

## Azure Preperation

1. Create an Azure storage account

    > modify the arguments to suit your environment

    ```bash
    az storage account create \
      --name thanosreceiver \
      --resource-group openshift \
      --location eastus \
      --sku Standard_RAGRS \
      --kind StorageV2
    ```

1. Get the account key and update the secret in `thanos-store-credentials.yaml`

    ```bash
    az storage account keys list -g openshift -n thanosreceiver
    ```

1. Create the Thanos Store Credentials Secret

    ```bash
    oc new-project thanos-receiver
    oc apply -f thanos-store-credentials.yaml
    ```

## Enabling User Workload Monitoring

> See [docs](https://docs.openshift.com/container-platform/4.7/monitoring/enabling-monitoring-for-user-defined-projects.html) for more indepth details.

1. Check the cluster-monitoring-config ConfigMap object

    ```bash
    oc -n openshift-monitoring get configmap cluster-monitoring-config -o yaml
    ```

1. Enable User Workload Monitoring by doing one of the following

    **If the `data.config.yaml` is not `{}` you should edit it and add the `enableUserWorkload: true` line manually.**

    ```bash
    oc -n openshift-monitoring edit configmap cluster-monitoring-config
    ```

    **Otherwise if its `{}` then you can run the following command safely.**

    ```bash
    oc patch configmap cluster-monitoring-config -n openshift-monitoring \
       -p='{"data":{"config.yaml": "enableUserWorkload: true\n"}}'
    ```

1. Check that the User workload monitoring is starting up

    ```bash
    oc -n openshift-user-workload-monitoring get pods
    ```

## Deploy Thanos Store Gateway

<!--

> we should be able to skip this because its in the yaml now.

1. Create a service account for the Thanos Store Gateway

    ```bash
    oc -n thanos-receiver create serviceaccount thanos-store-gateway
    oc -n thanos-receiver adm policy add-scc-to-user anyuid -z thanos-store-gateway
    ```
-->

1. Deploy the thanos store

    ```bash
    oc apply -f thanos-store.yaml
    ```

1. Deploy Thanos Receiver

    > Note we should be securing this via [OIDC / Bearer Tokens](https://www.openshift.com/blog/federated-prometheus-with-thanos-receive)

    ```bash
    oc -n thanos-receiver apply -f thanos-receive.yaml
    ```

1. Append remoteWrite settings to the cluster-monitoring config to forward cluster metrics to Thanos.

    ```bash
    oc -n openshift-monitoring edit configmaps cluster-monitoring-config
    ```

    ```yaml
      data:
        config.yaml: |
          ...
          prometheusK8s:
          ...
            remoteWrite:
              - url: "http://thanos-receive.thanos-receiver.svc.cluster.local:9091/api/v1/receive"
    ```

1. Append remoteWrite settings to the user-workload-monitoring config to forward user workload metrics to Thanos.

    **Check if the User Workload Config Map exists:**

    ```bash
    oc -n openshift-user-workload-monitoring get \
      configmaps user-workload-monitoring-config
    ```

    **If the config doesn't exist run:**

    ```bash
    oc apply -f user-workload-monitoring-config.yaml
    ```

    **Otherwise update it with the following:**

    ```bash
    oc -n openshift-user-workload-monitoring edit \
      configmaps user-workload-monitoring-config
    ```

    ```yaml
      data:
        config.yaml: |
          ...
          prometheus:
          ...
            remoteWrite:
              - url: "http://thanos-receive.thanos-receiver.svc.cluster.local:9091/api/v1/receive"
    ```

## Deploy Thanos Queryier

1. Deploy the thanos querier

    ```bash
    oc apply -f thanos-querier.yaml
    ```

## Deploy Grafana

1. create the grafana operator in the thanos-receiver namespace

    ```bash
    oc apply -f thanos-grafana-operator.yaml
    ```

1. create grafana instance and datasource for thanos

    > Change the password to something less default.

    ```bash
    oc -n thanos-receiver apply -f thanos-grafana.yaml
    ```

1. load up cluster metrics dashboards

    > Note: these were generated by the [generate-dashboards.sh](generate-dashboards.sh) script.

    ```bash
    oc -n thanos-receiver apply -f dashboards.yaml
    ```

1. get the Route URL for Grafana (remember its https) and login using username `root` and the password you updated to (or the default of `secret`).

    ```bash
    oc -n thanos-receiver get route grafana-route
    ```

1. Once logged in go to **Dashboards->Manage** and expand the **thanos-receiver** group and you should see the cluster metrics dashboards.  Click on the **Use Method / Cluster** Dashboard and you should see metrics.  \o/.

![screenshot of grafana with federated cluster metrics](./grafana-metrics.png)

repository: jamesread/mobb-docs

branch_name: refs/heads/main

extension: md

license_type: permissive

repo_name: jamesread/mobb-docs


text:
---
layout: post
title: Using Subversion with Mac OS X
tags: [svn]
---

- To create a repository:

```bash
svnadmin create ~/Documents/MySVN
```

- Edit the `conf/` files:
  - into `svnserve.conf`, remove comments before:
    - `anon-access = read`,
    - `auth-access = write`
    - and `password-db = passwd`
  - add a user/password into `passwd`
- To run your SVN server, run:

```bash
svnserve -d -r ~/Documents/MySVN
```

license: MIT

repository: Bootstragram/bootstragram-blog

gha_language: JavaScript

gha_license_id: MIT

repo_name: Bootstragram/bootstragram-blog


text:
# Clojure

Here you can find useful references under Clojure topic.

- [How to write Clojure application](https://www.exoscale.com/syslog/clojure-application-tutorial/)

  Do you want to know how the big company writing Clojure application? Here is the tutorial provided by exoscale.

repository: hqxsn/Awesome-Bookmarks-From-Globe

branch_name: refs/heads/master

repo_name: hqxsn/Awesome-Bookmarks-From-Globe


text:
## install

Usage: `yeoman install <packageName>`, `yeoman install <package1> <package2>`

Installs a package and any packages that this depends on using Twitter Bower.

By default, running `yeoman install packageName` will install the dependency in your projects `app/components` folder.

Example:

{% highlight sh %}
yeoman install backbone

# or if you wish to install multiple packages at once..
yeoman install jquery spine
{% endhighlight %}

As mentioned, the files for these dependencies will be added to `app/components`. If you wish to use any of them you will need to manually include a script/file reference to the relevant source files.

Example:

{% highlight html %}

{% endhighlight %}

If installing a dependency which has its own dependencies described, these dependencies will also be pulled in.

Example:

{% highlight sh %}
yeoman install backbone
{% endhighlight %}

will actually also install Underscore.js and jQuery.js as these are required for Backbone to function correctly.

`yeoman install` also supports installing packages using more than just the package name. Namely:

{% highlight sh %}
yeoman install jquery
yeoman install git://github.com/components/jquery.git
yeoman install components/jquery (same as above)
yeoman install http://foo.com/jquery.awesome-plugin.js
yeoman install ./repos/jquery
{% endhighlight %}

As you can see, packages can be installed by name, Git endpoint, GitHub shorthand, URL or local path. If you install and URL that is a zip or tar file, yeoman will automatically extract the contents of it. When tags are available in the endpoint, you can specify a semver tag to fetch concrete versions:

{% highlight sh %}
yeoman install jquery#1.8.1
yeoman install git://github.com/components/jquery.git#~1.8.1
yeoman install components/jquery#1.8.x
{% endhighlight %}

More in the [Bower docs](https://github.com/twitter/bower/blob/master/README.md#usage)

repository: duoku/yeoman

repo_name: duoku/yeoman


text:
## League of Legends - Champion Database

The sole intention of this database is to provide a collection of League of Legends resources for fanbase sites and applications.

### License

League of Legends - Champion Database uses [unlicense](http://unlicense.org/)

### Copyright

League of Legends, characters, images and all other copyrighted content related to League of Legends are the property of Riot Games, Inc. All rights reserved.

### Legal Notices Regarding the usage of images and data from Riot Games

Riot Games directly allows 3rd party websites to use their art and champion skins.

From their FAQ obtained by emailing<EMAIL_ADDRESS>
> Q: Can I use your art/logo/champion skins on my website?
> A: As long as you aren't charging people for access to your website, you may use any copyrighted assets we freely distribute in the game client. This includes all champion skin splash images.
>
> The exception: you can't use the Riot Games logo or other trademarks under any circumstances.

license: Unlicense


text:
1.7.0 / 2016-08-04
==================

  * automatically generate an id when one is not specified (for accessibility)

1.6.1 / 2016-07-30
==================

  * bump form-parse

1.6.0 / 2016-07-23
==================

  * adding additional css hooks for fields and all field types
  * remove superfluous propTypes

1.5.1 / 2016-07-22
==================

  * lint fix

1.5.0 / 2016-07-22
==================

  * improving custom validation support

1.4.2 / 2016-07-13
==================

  * input-field: add `accept` support to `type=file` inputs (#15)

1.4.1 / 2016-04-21
==================

  * adding autofocus attr to input to enable autofocus even during server-side rendering

1.4.0 / 2016-04-19
==================

  * switch to remarkable for markdown rendering

1.3.0 / 2016-04-19
==================

  * adding autofocus support

1.2.1 / 2016-02-28
==================

  * supporting markdown for field descriptions

1.2.0 / 2016-02-28
==================

  * adding support for focus and blur events
  * adding description to fields

1.1.0 / 2015-11-15
==================

  * precompile on publish

1.0.1 / 2015-11-15
==================

  * adding main to package.json

1.0.0 / 2015-11-14
==================

  * porting to build with mako instead of component/duo

0.4.1 / 2015-10-20
==================

  * form: add autocomplete attribute

0.4.0 / 2015-09-02
==================

  * adding custom css class hooks

0.3.0 / 2015-08-26
==================

  * validation errors only show after form submission by default

0.2.0 / 2015-08-25
==================

  * adding async validation support

0.1.2 / 2015-08-24
==================

  * input-field, text-field: properly clearing custom validation errors
  * select-field: fixed bug where options were not being set
  * tests: cleanup all around

0.1.1 / 2015-08-17
==================

  * field: adding `class` attribute
  * field types: adding CSS hook for each type

0.1.0 / 2015-08-17
==================

  * field: renamed publicly as `FormField`
  * field: adding `has-error` css hook

0.0.2 / 2015-08-17
==================

  * meta: using jsx pragma instead of babelrc (until babel/babel#2214 is resolved)
  * checkbox-field: adding `checked` attribute

0.0.1 / 2015-08-13
==================

:sparkles:

repository: dominicbarnes/deku-forms

repo_name: dominicbarnes/deku-forms


text:
# FastImage [![travis][travis-image]][travis-url]

[travis-image]: https://img.shields.io/travis/bmuller/fastimage/master.svg
[travis-url]: https://travis-ci.org/bmuller/fastimage

This is an implementation of the excellent Ruby library [FastImage](https://github.com/sdsykes/fastimage) - but for Python.

FastImage finds the size or type of an image given its uri by fetching as little as needed.

## Installation

```
pip install fastimage
```

## Usage

Usage is pretty dang simple.

```python
import asyncio
from fastimage.detect import get_size

loop = asyncio.get_event_loop()
url = "http://stephensykes.com/images/ss.com_x.gif"
width, height = loop.run_until_complete(get_size(url))
print("Size:", width, "x", height)
```

which will poop out:

```bash
Size: 266 x 56
```

You can also just get the image type:
```python
import asyncio
from fastimage.detect import get_type

loop = asyncio.get_event_loop()
url = "http://stephensykes.com/images/ss.com_x.gif"
result = loop.run_until_complete(get_type(url))
print("Type:", result)
```

which will poop out:

```bash
Type: gif
```

Right now, sizes can be deduced from webp / gif / jpg / png.  Additionally, it can detect the type (but not size) of bmp / tiff.

repository: pokotyamu/fastimage

extension: markdown

gha_language: Python

repo_name: pokotyamu/fastimage


text:
[//]: # (title: Create an app using C Interop and libcurl – tutorial)

This tutorial demonstrates how to use IntelliJ IDEA to create a command-line application. You'll learn how to create
a simple HTTP client that can run natively on specified platforms using Kotlin/Native and the `libcurl` library.

The output will be an executable command-line app that you can run on macOS and Linux and make simple HTTP GET requests.

> While it is possible to use the command line, either directly or by combining it with a script file (such as a `.sh` or
> a `.bat` file), this approach doesn't scale well for big projects with hundreds of files and libraries. In this case, it is
> better to use the Kotlin/Native compiler with a build system, as it helps download and cache the Kotlin/Native
> compiler binaries and libraries with transitive dependencies and run the compiler and tests. Kotlin/Native can use the
> [Gradle](gradle.md) build system through the [`kotlin-multiplatform`](multiplatform-discover-project.md#multiplatform-plugin)
> Plugin.
>

To get started, install the latest version of [IntelliJ IDEA](https://www.jetbrains.com/idea/download/index.html).
The tutorial is suitable for both IntelliJ IDEA Community Edition and IntelliJ IDEA Ultimate.

## Create a Kotlin/Native project

1. In IntelliJ IDEA, select **File | New | Project**.
2. In the panel on the left, select **Kotlin Multiplatform | Native Application**.
3. Specify the name and select the folder where you'll save your application.

   ![New project. Native application in IntelliJ IDEA](native-file-new.png){width=700}

4. Click **Next** and then **Finish**.

IntelliJ IDEA will create a new project with the files and folders you need to get you started. It's important to understand that
an application written in Kotlin/Native can target different platforms if the code does not have platform-specific
requirements. Your code is placed in a folder named `NativeMain` with its corresponding `NativeTest`. For this tutorial,
keep the folder structure as is.

![Native application project structure](native-project-structure.png){width=700}

Along with your new project, a `build.gradle(.kts)` file is generated. Pay special attention to the following
in the build file:

<tabs group="build-script">
<tab title="Kotlin" group-key="kotlin">

```kotlin
kotlin {
    val hostOs = System.getProperty("os.name")
    val isMingwX64 = hostOs.startsWith("Windows")
    val nativeTarget = when {
        hostOs == "Mac OS X" -> macosX64("native")
        hostOs == "Linux" -> linuxX64("native")
        isMingwX64 -> mingwX64("native")
        else -> throw GradleException("Host OS is not supported in Kotlin/Native.")
    }

    nativeTarget.apply {
        binaries {
            executable {
                entryPoint = "main"
            }
        }
    }
}

```
</tab>
<tab title="Groovy" group-key="groovy">

```groovy
kotlin {
    def hostOs = System.getProperty("os.name")
    def isMingwX64 = hostOs.startsWith("Windows")
    def nativeTarget
        if (hostOs == "Mac OS X") nativeTarget = macosX64('native')
        else if (hostOs == "Linux") nativeTarget = linuxX64("native")
        else if (isMingwX64) nativeTarget = mingwX64("native")
        else throw new FileNotFoundException("Host OS is not supported in Kotlin/Native.")

    nativeTarget.with {
        binaries {
            executable {
                entryPoint = 'main'
            }
        }
    }
}
```

</tab>
</tabs>

* Targets are defined using `macOSX64`, `linuxX64`, and `mingwX64` for macOS, Linux, and Windows. For a complete
  list of supported platforms, see the [Kotlin Native overview](native-overview.md#target-platforms).
* The entry itself defines a series of properties to indicate how the binary is generated and the entry
  point of the applications. These can be left as default values.
* C interoperability is configured as an additional step in the build. By default, all the symbols from C are
  imported to the `interop` package. You may want to import the whole package in `.kt` files. Learn more about
  [how to configure](multiplatform-discover-project.md#multiplatform-plugin) it.

## Create a definition file

When writing native applications, you often need access to certain functionalities that are not included in the [Kotlin
standard library](https://kotlinlang.org/api/latest/jvm/stdlib/), such as making HTTP requests, reading and writing from
disk, and so on.

Kotlin/Native helps consume standard C libraries, opening up an entire ecosystem of functionality that exists
for pretty much anything you may need. Kotlin/Native is already shipped with a set of prebuilt [platform libraries](native-platform-libs.md),
which provide some additional common functionality to the standard library.

An ideal scenario for interop is to call C functions as if you are calling Kotlin functions, following the same
signature and conventions. This is when the `cinterop` tool comes in handy. It takes a C library and generates the
corresponding Kotlin bindings, so that the library can be used as if it were Kotlin code.

To generate these bindings, create a library definition `.def` file that contains some information about the necessary
headers. In this app, you'll need the `libcurl` library to make some HTTP calls. To create a definition file:

1. Select the `src` folder and create a new directory with **File | New | Directory**.
2. Name new directory **nativeInterop/cinterop**. This is the default convention for header file locations, though it can
   be overridden in the `build.gradle(.kts)` file if you use a different location.
3. Select this new subfolder and create a new `libcurl.def` file with **File | New | File**.
4. Update your file with the following code:

    ```c
    headers = curl/curl.h
    headerFilter = curl/*

    compilerOpts.linux = -I/usr/include -I/usr/include/x86_64-linux-gnu
    linkerOpts.osx = -L/opt/local/lib -L/usr/local/opt/curl/lib -lcurl
    linkerOpts.linux = -L/usr/lib/x86_64-linux-gnu -lcurl
    ```

   * `headers` is the list of header files to generate Kotlin stubs. You can add multiple files to this entry,
   separating each with a `\` on a new line. In this case, it's only `curl.h`. The referenced files need to be available
   on the system path (in this case, it's `/usr/include/curl`).
   * `headerFilter` shows what exactly is included. In C, all the headers are also included when one file references
   another one with the `#include` directive. Sometimes it's not necessary, and you can add this parameter
   [using glob patterns](https://en.wikipedia.org/wiki/Glob_(programming)) to fine-tune things.

     `headerFilter` is an optional argument and is mostly used when the library is installed as a system library. You don't
   want to fetch external dependencies (such as system `stdint.h` header) into the interop library. It may be important to
   optimize the library size and fix potential conflicts between the system and the provided Kotlin/Native compilation
   environment.

   * The next lines are about providing linker and compiler options, which can vary depending on different target platforms.
   In this case, they are macOS (the `.osx` suffix) and Linux (the `.linux` suffix). Parameters without a suffix are also
   possible (for example, `linkerOpts=`) and applied to all platforms.

The convention is that each library gets its definition file, usually with the same name as the library. For more
information on all the options available to `cinterop`, see [the Interop section](native-c-interop.md).

> You need to have the `curl` library binaries on your system to make the sample work. On macOS and Linux, it is usually
> included. On Windows, you can build it from [sources](https://curl.haxx.se/download.html) (you'll need Visual Studio or
> Windows SDK Commandline tools). For more details, see the [related blog post](https://jonnyzzz.com/blog/2018/10/29/kn-libcurl-windows/).
> Alternatively, you may want to consider a [MinGW/MSYS2](https://www.msys2.org/) `curl` binary.
>
{type="note"}

## Add interoperability to the build process

To use header files, make sure they are generated as a part of the build process. For this, add the following
entry to the `build.gradle(.kts)` file:

<tabs group="build-script">
<tab title="Kotlin" group-key="kotlin">

```kotlin
nativeTarget.apply {
    compilations.getByName("main") {    // NL
        cinterops {                     // NL
            val libcurl by creating     // NL
        }                               // NL
    }                                   // NL
    binaries {
        executable {
            entryPoint = "main"
        }
    }
}
```

</tab>
<tab title="Groovy" group-key="groovy">

```groovy
nativeTarget.with {
    compilations.main { // NL
        cinterops {     // NL
            libcurl     // NL
        }               // NL
    }                   // NL
    binaries {
        executable {
            entryPoint = 'main'
        }
    }
}
```

</tab>
</tabs>

The new lines are marked with `// NL`. First, `cinterops` is added, and then an entry for each `def` file. By default,
the name of the file is used. You can override this with additional parameters:

<tabs group="build-script">
<tab title="Kotlin" group-key="kotlin">

```kotlin
val libcurl by creating {
    defFile(project.file("src/nativeInterop/cinterop/libcurl.def"))
    packageName("com.jetbrains.handson.http")
    compilerOpts("-I/path")
    includeDirs.allHeaders("path")
}
```

</tab>
<tab title="Groovy" group-key="groovy">

```groovy
libcurl {
    defFile project.file("src/nativeInterop/cinterop/libcurl.def")
    packageName 'com.jetbrains.handson.http'
    compilerOpts '-I/path'
    includeDirs.allHeaders("path")
}
```

</tab>
</tabs>

See the [Interoperability with C](native-c-interop.md) section for more details on the available options.

## Write the application code

Now you have the library and the corresponding Kotlin stubs and can use them from your application. For this tutorial,
convert the [simple.c](https://curl.haxx.se/libcurl/c/simple.html) example to Kotlin.

In the `src/nativeMain/kotlin/` folder, update your `Main.kt` file with the following code:

```kotlin
import kotlinx.cinterop.*
import libcurl.*

fun main(args: Array<String>) {
    val curl = curl_easy_init()
    if (curl != null) {
        curl_easy_setopt(curl, CURLOPT_URL, "https://example.com")
        curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L)
        val res = curl_easy_perform(curl)
        if (res != CURLE_OK) {
            println("curl_easy_perform() failed ${curl_easy_strerror(res)?.toKString()}")
        }
        curl_easy_cleanup(curl)
    }
}
```

As you can see, explicit variable declarations are eliminated in the Kotlin version, but everything else is pretty much
the same as the C version. All the calls you'd expect in the `libcurl` library are available in the Kotlin equivalent.

> This is a line-by-line literal translation. You could also write this in a more Kotlin idiomatic way.
>

## Compile and run the application

1. Compile the application. To do that, call `runDebugExecutableNative` in the list of run Gradle tasks or use the following
   command in the terminal:

    ```bash
    ./gradlew runDebugExecutableNative
    ```
    In this case, the `cinterop` generated part is implicitly included in the build.

2. If there are no errors during compilation, click the green **Run** icon in the gutter beside the `main()` method or
use the **Alt+Enter** shortcut to invoke the launch menu in IntelliJ IDEA.

    IntelliJ IDEA opens the **Run** tab and shows the output — the contents of `https://example.com`:

    ![Application output with HTML-code](native-output.png){width=700}

You can see the actual output because the call `curl_easy_perform` prints the result to the standard output. You could
hide this using `curl_easy_setopt`.

> You can get the full code [here](https://github.com/Kotlin/kotlin-hands-on-intro-kotlin-native).
>
{type="note"}

repository: JetBrains/kotlin-web-site

repo_name: JetBrains/kotlin-web-site


text:
I prefer to be the second type.

I’m a stupidly curious guy with crazy imaginations. But I’m not into everything!, I don’t care about most of the things. Honestly as bad as it sounds, I don’t even know the current President of my country. The last one I knew was Dr. APJ Abdul Kalam. The only reason I knew of him was because he is a Scientist and my academics back then had a subject General Knowledge in curriculum.

<!--/excerpt-->

>I’m not crazy my reality is just different from yours. — Lewis Carroll, Alice in Wonderland

**Let’s start with what kind of Guy I am (from my perspective)**

Mostly, I live in my own world of Coding, Exploring the stuff that interests me. I’m too emotional about what I love, but I don’t essentially show that every time. I love Nature — Forests, Mountains and Water bodies. I love meeting new people, but unfortunately once they are out of sight, they are out of my mind.

**Lets start from the beginning, the very beginning — My Dreams as a Child**

![MegaMing baby picture](/public/img/my-story/baby.jpeg)

I always wanted to become a Scientist. I love the look of the Scientists in long white Aprons, with gloves, test tubes, glasses on they nose. I always wanted to become a Scientist with a thought that I can create whatever I want to If I become a scientist. Example: I was always curious about how we live, whats wrong with Oxygen, Carbondioxide, Why humans live on O2 but Trees live on CO2. What makes humans move and why trees can’t move.

### School and College Confused me a lot

![School kid picture](/public/img/my-story/schoolboy.png)

*School in fact, confused me a lot with the little things I was taught*. I thought If I could become a Scientist I could solve the mysteries in my head. In college, I studied Genetics just for this, then I did a course on Chemoinformatics, which completely changed my way from genetics. *I took Masters in Bioinformatics, because of the love for both computers and biology*. I almost spent 2 years in doing academic research on Computational Drug Designing.

### Computational Drug Discovery was fascinating

![CADD Image](/public/img/my-story/cadd.png)

All the years of my research career in Computational Drug Discovery, I’m so attached to the computers, because all the simulations need to be done on Linux machines sometimes HPCs :) .

Then worked as technical associate, later moved into programming and finally settled as a Developer as profession. But I still feel the thirst for scientific knowledge, reasoning and discovery. I wish I could restart my scientific research career soon or later. I’m actually planning something on this.

### Being Developer is awesome

![Code Editor](/public/img/my-story/editor.png)

Being developer and being scientists are almost same, but if you are a scientist, you create something for the world, and if you are a developer, you create something for the fun ;) But, honestly both improve the life of Human Race in their own perspectives ways.

> The best part being a Coder is you can create anything you want to. PS: Atleast that’s what you feel ;)

Currently I’m working on my first startup [Invaana](https://invaana.com). Let’s see what life has planned for me or what I’ll make out of my life ;)


text:
# justify-self

https://developer.mozilla.org/en-US/docs/Web/CSS/justify-self

## auto
```css
.selector {
  composes: auto from 'hydrogencss/justify-self.css'
}
```

or:
```css
.selector {
  composes: auto from 'hydrogencss/justify-self/auto.css'
}
```

## normal
```css
.selector {
  composes: normal from 'hydrogencss/justify-self.css'
}
```

or:
```css
.selector {
  composes: normal from 'hydrogencss/justify-self/normal.css'
}
```

## stretch
```css
.selector {
  composes: stretch from 'hydrogencss/justify-self.css'
}
```

or:
```css
.selector {
  composes: stretch from 'hydrogencss/justify-self/stretch.css'
}
```

repository: eddiemoore/hydrogencss

repo_name: eddiemoore/hydrogencss


text:
# Unity asset bundle compressor

This program will compress Unity asset bundles with LZ4 compression, saving disk space and improving load times. To use this program, drag a folder or a unity3d file on to the .exe

Uses [AssetTools.NET](https://github.com/nesrak1/AssetsTools.NET#bundle-file-loading) Copyright (c) 2020 nesrak1

gha_language: C#


text:
## Contributing

[fork]: /fork
[pr]: /compare
[style]: https://standardjs.com/
[code-of-conduct]: CODE_OF_CONDUCT.md

Hi there! We're thrilled that you'd like to contribute to this project. Your help is essential for keeping it great.

Please note that this project is released with a [Contributor Code of Conduct][code-of-conduct]. By participating in this project you agree to abide by its terms.

## Issues and PRs

If you have suggestions for how this project could be improved, or want to report a bug, open an issue! We'd love all and any contributions. If you have questions, too, we'd love to hear them.

We'd also love PRs. If you're thinking of a large PR, we advise opening up an issue first to talk about it, though! Look at the links below if you're not sure how to open a PR.

## Submitting a pull request
### First time contributors
We should encourage first time contributors. A good inspiration on this can be found [here](http://www.firsttimersonly.com/). As pointed out:

> If you are an OSS project owner, then consider marking a few open issues with the label first-timers-only. The first-timers-only label explicitly announces:

> "I'm willing to hold your hand so you can make your first PR. This issue is rather a bit easier than normal. And anyone who’s already contributed to open source isn’t allowed to touch this one!"

By labeling issues with this `first-timers-only` label we help first time contributors step up their game and start contributing.

### Pull request step-by-step guide

Good pull requests - patches, improvements, new features - are a fantastic
help. They should remain focused in scope and avoid containing unrelated
commits.

**Please ask first** before embarking on any significant pull request (e.g.
implementing features, refactoring code, porting to a different language),
otherwise you risk spending a lot of time working on something that the
project's developers might not want to merge into the project.

Please adhere to the coding conventions used throughout a project (indentation,
accurate comments, etc.) and any other requirements (such as test coverage).

Follow this process if you'd like your work considered for inclusion in the
project:

1. [Fork](http://help.github.com/fork-a-repo/) the project, clone your fork,
   and configure the remotes:

   ```bash
   # Clone your fork of the repo into the current directory
   git clone git@github.com:SvanBoxel/delete-merged-branch.git
   # Navigate to the newly cloned directory
   cd delete-merged-branch
   # Assign the original repo to a remote called "upstream"
   git remote add upstream git@github.com:SvanBoxel/delete-merged-branch.git
   ```

2. If you cloned a while ago, get the latest changes from upstream:

   ```bash
   git checkout <dev-branch>
   git pull upstream <dev-branch>
   ```

3. Create a new topic branch (off the master branch) to
   contain your feature, change, or fix:

   ```bash
   git checkout -b <issue-number>-<topic-branch-name>
   ```

   We recommend having an issue for every improvement you make. Please prepend your branch name with the issue number. eg. issue #381 related to a failing head image: `381-fix-header-image`

4. Commit your changes in logical chunks. Please adhere to these [AngularJS Git Commit Message Conventions](https://docs.google.com/document/d/1QrDFcIiPjSLDn3EL15IJygNPiHORgU1_OOAqWjiDU5Y)
   or your code is unlikely be merged into the main project. Use Git's
   [interactive rebase](https://help.github.com/articles/interactive-rebase)
   feature to tidy up your commits before making them public.

5. Locally merge (or rebase) the upstream development branch into your topic branch:

   ```bash
   git pull [--rebase] upstream <dev-branch>
   ```

6. Push your topic branch up to your fork:

   ```bash
   git push origin <topic-branch-name>
   ```

7. [Open a Pull Request](https://help.github.com/articles/using-pull-requests/)
    with a clear title and description.

### Conventions of commit messages

Adding features on repo

```bash
git commit -m "feat: message about this feature"
```

Fixing features on repo

```bash
git commit -m "fix: message about this update"
```

Removing features on repo

```bash
git commit -m "refactor: message about this" -m "BREAKING CHANGE: message about the breaking change"
```

**IMPORTANT**: By submitting a patch, you agree to allow the project owner to license your work under the same license as that used by the project.

## Resources

- [How to Contribute to Open Source](https://opensource.guide/how-to-contribute/)
- [Using Pull Requests](https://help.github.com/articles/about-pull-requests/)
- [GitHub Help](https://help.github.com)

license: ISC

repository: SvanBoxel/delete-merged-branch

gha_license_id: ISC

repo_name: SvanBoxel/delete-merged-branch


text:
# Mutatone

Mutatone generates melodies using evolutionary algorithms.

[Try it out here](http://toxicsli.me/mutatone). Click the Play button
for each melody, then select your two favorites and click on the Breed
button for each one. New offspring melodies appear! Repeat.

This is written in ClojureScript using the new HTML5 Web Audio API,
which both Chrome and Firefox now support.

I ([@graue](https://github.com/graue)) wrote it at the December 2013
[NYC Monthly Music Hackathon](http://monthlymusichackathon.org), where
the theme was "Automatic Music". You can [see many other cool hacks
here](https://www.hackerleague.org/hackathons/automatic-music-hackathon/hacks).
(Check out H.C.K.T., Browser FX Pedal and the tic-tac-toe hack.) Many
thanks to the hackathon organizers and sponsors for providing the space
and motivation to make this.

repository: graue/mutatone

repo_name: graue/mutatone


text:
# GitLab Geo

This document will instruct you to set up GitLab Geo using GDK.

Geo allows you to replicate a whole GitLab instance. Customers use this for
Disaster Recovery, as well as to offload read-only requests to secondary
instances. For more, see
[GitLab Geo](https://about.gitlab.com/solutions/geo/) or
[Replication (Geo)](https://docs.gitlab.com/ee/administration/geo/replication/).

## Prerequisites

Development on GitLab Geo requires two GDK instances running side-by-side.
You can use an existing `gdk` instance based on the [Set up GDK](../set-up-gdk.md#develop-against-the-gitlab-project-default) documentation as the primary node.

### Secondary

Now we'll create a secondary instance in a `gdk-geo` folder to act as
a secondary node. We'll configure unique ports for the new instance so
that it can run alongside the primary.

```bash
gdk init gdk-geo
cd gdk-geo
```

Add the following to `gdk.yml` file:

```yaml
---
geo:
  enabled: true
  node_name: gdk-geo
gitlab_pages:
  enabled: enabled
  port: 3011
tracer:
  jaeger:
    enabled: false
port: 3001
webpack:
  port: 3809
```

Then run the following command:

```bash
# Assuming your primary GDK instance lives in parallel folders:
gdk install gitlab_repo=../gdk/gitlab
```

When seeding begins, cancel it (Ctrl-C) since we will delete the data anyway.

Then run the following commands:

```bash
gdk start postgresql
gdk start postgresql-geo
make geo-setup
```

## Database replication

For GitLab Geo, you will need a primary/secondary database replication defined.
There are a few extra steps to follow.

### Prepare primary for replication

In your primary instance (`gdk`) you need to prepare the database for
replication. This requires the PostgreSQL server to be running, so we'll start
the server, perform the change (via a `make` task), and then kill and restart
the server to pick up the change:

```bash
# terminal window 1:
cd gdk
gdk start postgresql
make postgresql-replication-primary
gdk restart postgresql
make postgresql-replication-primary-create-slot
gdk restart postgresql
```

### Set up replication on secondary

Because we'll be replicating the primary database to the secondary, we need to
remove the secondary's PostgreSQL data folder:

```bash
# terminal window 2:
cd gdk-geo
rm -r postgresql
```

Now we need to add a symbolic link to the primary instance's data folder:

```bash
# From the gdk-geo folder:
ln -s ../gdk/postgresql postgresql-primary
```

Initialize a secondary database and setup replication:

```bash
# terminal window 2:
make postgresql-replication-secondary
```

### Running tests

The secondary has a read-write tracking database, which is necessary for some
Geo tests to run. However, its copy of the replicated database is read-only, so
tests will fail to run.

You can add the tracking database to the primary node by running:

```bash
# From the gdk folder:
gdk start

# In another terminal window
make geo-setup
```

This will add both development and test instances, but the primary will continue
to operate *as* a primary except in tests where the current Geo node has been
stubbed.

To ensure the tracking database is started, restart GDK. You will need to use
`gdk start` to be able to run the tests.

## Copy database encryption key

The primary and the secondary nodes will be using the same secret key
to encrypt attributes in the database. To copy the secret from your primary to your secondary:

1. Open `gdk/gitlab/config/secrets.yml` with your editor of choice
1. Copy the value of `development.db_key_base`
1. Paste it into `gdk-geo/gitlab/config/secrets.yml`

## SSH cloning

To be able to clone over SSH on a secondary, follow the instruction on how
to set up [SSH](ssh.md), including [SSH key lookup from database](ssh.md#ssh-key-lookup-from-database).

## Configure Geo nodes

### Add primary node

There is a rake task that can add the primary node:

```bash
cd gdk/gitlab

bundle exec rake geo:set_primary_node
```

### Add secondary node

There isn't a convenient rake task to add the secondary node because the command
must be run on the secondary, but written on the primary. So we must get the
name and manually add the node. Open a terminal window on the secondary node.
This will output the secondary node's name.

```bash
cd gdk-geo/gitlab

bundle exec rails runner 'puts GeoNode.current_node_name'
```

1. Visit the **primary** node's **Admin Area ➔ Geo Nodes** (`/admin/geo/nodes`)
   in your browser.
1. Click the **New node** button.
1. Using the *exact* output from the `puts GeoNode.current_node_name` command,
   fill in the **Name** and **URL** fields for the **secondary** node.
1. **Do not** check the box 'This is a primary node'.
1. Click the **Add node** button.

![Adding a secondary node](img/adding_a_secondary_node.png)

## Geo-specific GDK commands

### `make geo-primary-migrate`

Use this when your checked out files have changed, and e.g. your instance or
tests are now erroring. For example, after you pull master, but you don't care
to update dependencies right now. Or maybe you checked out someone else's
branch.

* Bundle installs to ensure gems are up-to-date
* Migrates main DB and tracking DB (be sure to run `make geo-secondary-migrate` on
your secondary if you have Geo migrations)
* Prepares main and tracking test DBs
* Checks out schemas to get rid of irrelevant diffs (not done in
   `make geo-primary-migrate` because you may have created a migration)

### `make geo-primary-update`

Same as `make geo-primary-migrate`, but also:

* Does `gdk update`
* Checks out and pulls master
* Updates dependencies (e.g. if Gitaly is erroring)
* Rebuilds FDW tables in test DB
* Finally does `gdk diff-config` so you can see a summary of how your configs
  differ from a fresh install

### `make geo-secondary-migrate`

Similar to `make geo-primary-migrate` but for your local secondary.

### `make geo-secondary-update`

Similar to `make geo-primary-update` but for your local secondary.

## Troubleshooting

### postgresql-geo/data exists but is not empty

If you see this error during setup because you have already run `make geo-setup` once:

```
initdb: directory "postgresql-geo/data" exists but is not empty
If you want to create a new database system, either remove or empty
the directory "postgresql-geo/data" or run initdb
with an argument other than "postgresql-geo/data".
make: *** [postgresql/geo] Error 1
```

Then you may delete or move that data in order to run `make geo-setup` again.

```bash
$ mv postgresql-geo/data postgresql-geo/data.backup
```

### GDK update command error on secondaries

You will see the following error after running `gdk update` on your local Geo
secondary. It is ok to ignore. Your local Geo secondary does not have or need a
test DB, and this error occurs on the very last step of `gdk update`.

```bash
cd /Users/foo/Developer/gdk-geo/gitlab && \
      bundle exec rake db:migrate db:test:prepare
rake aborted!
ActiveRecord::StatementInvalid: PG::ReadOnlySqlTransaction: ERROR:  cannot execute DROP DATABASE in a read-only transaction
: DROP DATABASE IF EXISTS "gitlabhq_test"
/Users/foo/.rbenv/versions/2.6.3/bin/bundle:23:in `load'
/Users/foo/.rbenv/versions/2.6.3/bin/bundle:23:in `<main>'

Caused by:
PG::ReadOnlySqlTransaction: ERROR:  cannot execute DROP DATABASE in a read-only transaction
/Users/foo/.rbenv/versions/2.6.3/bin/bundle:23:in `load'
/Users/foo/.rbenv/versions/2.6.3/bin/bundle:23:in `<main>'
Tasks: TOP => db:test:load => db:test:purge
(See full trace by running task with --trace)
make: *** [gitlab-update] Error 1
```

### FDW is no longer working even though you have it enabled, after migrations or `gdk update`

You need to rebuild FDW tables.

If your local primary is in `~/Developer/gdk`:

```bash
cd ~/Developer/gdk
gdk start
make postgresql/geo-fdw/test/rebuild
```

And if your local secondary is in `~/Developer/gdk-geo`:

```bash
cd ~/Developer/gdk-geo
gdk start
make postgresql/geo-fdw/development/rebuild
```

Also see [Useful aliases](#useful-aliases) above.

## Enabling Docker Registry replication

For information on enabling Docker Registry replication in GDK, see
[Docker Registry replication](geo-docker-registry-replication.md).

repository: chriscasano/gitlab-development-kit

repo_name: chriscasano/gitlab-development-kit


text:
# Node.js Mentorship Team Meeting 2018-11-17

## Links

* **Recording**: https://www.youtube.com/watch?v=7H90G3FztyA
* **GitHub Issue:** No issue created
* **Previous Minutes:** https://github.com/nodejs/mentorship/blob/master/meeting/2018-11-02.md

## Present

+ Ahmad Bamieh ([@Bamieh](https://github.com/bamieh))
  A.J. Roberts ([@detrohutt](https://github.com/detrohutt))
- Dan Shaw ([@dshaw](https://github.com/dshaw))
- Benjamin Coe ([@bcoe](https://github.com/bcoe))
- David Guttman ([@davidguttman](https://github.com/davidguttman))
- Jennifer Bland ([@ratracegrad](https://github.com/ratracegrad))

### Agenda

Extracted from mentorship-agenda labelled issues and pull requests from the mentorship repo prior to the meeting.

- No new issues

**TOPIC**

Mentorship Team Meeting Notes

Gather feedback from mentors and mentees and the mentorship team about the last cohort to get ready for setting up the next round.
Feedback revolved around items in this issue: https://github.com/nodejs/mentorship/issues/14

Process:
- Send an email to applicants to thank them and inform them that we have recieved their form.
- Change application signup form:
  - List the scopes the mentees can join in the cohort, this way we can better match them to their interest. (suggested by Jennifer)
  - Follow up email when people submit the form, to know that we got form and they are listed.
  - Send an email to everyone that signed up already, ask them to fill the new form.

Duration:
- Preferred mentorship duration: 2-3 months

Time commitment:
- 1-2 hours per week for mentors
- Mentees need also to put additional time to work towards their mentorship goals and update their mentorship diary.

Channels:
- Slack, github, and Zoom are a good combination to achieve the goals of mentorship. No need to modify the channels.

### Youtube Comments

Questions were addressed

repository: imtiyazjmi/mentorship

repo_name: imtiyazjmi/mentorship


text:
# Onda.jl

[![Build Status](https://travis-ci.com/beacon-biosignals/Onda.jl.svg?token=Jbjm3zfgVHsfbKqsz3ki&branch=master)](https://travis-ci.com/beacon-biosignals/Onda.jl)
[![codecov](https://codecov.io/gh/beacon-biosignals/Onda.jl/branch/master/graph/badge.svg?token=D0bcI0Rtsw)](https://codecov.io/gh/beacon-biosignals/Onda.jl)
[![](https://img.shields.io/badge/docs-stable-blue.svg)](https://beacon-biosignals.github.io/Onda.jl/stable)
[![](https://img.shields.io/badge/docs-dev-blue.svg)](https://beacon-biosignals.github.io/Onda.jl/dev)

[Take The Tour](https://github.com/beacon-biosignals/Onda.jl/tree/master/examples/tour.jl)

[See Other Examples](https://github.com/beacon-biosignals/Onda.jl/tree/master/examples)

Onda.jl is a Julia package for reading/writing [Onda](https://github.com/beacon-biosignals/OndaFormat) datasets.

This package follows the [YASGuide](https://github.com/jrevels/YASGuide).

## Installation

To install Onda for development, run:

```
julia -e 'using Pkg; Pkg.develop(PackageSpec(url="https://github.com/beacon-biosignals/Onda.jl"))'
```

This will install Onda to the default package development directory, `~/.julia/dev/Onda`.

gha_language: Julia


text:
# havalo-kvs-client

A client for the Havalo K,V store RESTful API.

Makes aggressive use of kolich-httpclient4-closure backed by the Apache Commons HttpClient 4.x.  Also, uses Google's GSON library for all JSON related "stuph" under-the-hood.

Written in Java 7, but can be cross compiled against Java 6 if desired.

## Latest Version

The latest stable version of this library is 1.4.

## Resolvers

If you wish to use this artifact, you can easily add it to your existing Maven or SBT project using my GitHub hosted Maven2 repository.

### SBT

```scala
resolvers += "Kolich repo" at "http://markkolich.github.com/repo"

val havaloClient = "com.kolich" % "havalo-kvs-client" % "1.4" % "compile"
```

### Maven

```xml
<repository>
  <id>Kolichrepo</id>
  <name>Kolich repo</name>
  <url>http://markkolich.github.io/repo/</url>
  <layout>default</layout>
</repository>

<dependency>
  <groupId>com.kolich</groupId>
  <artifactId>havalo-kvs-client</artifactId>
  <version>1.4</version>
  <scope>compile</scope>
</dependency>
```

## Usage

### Instantiate a HavaloClient

Before you can make API requests, you'll need to instantiate a `HavaloClient` backed by an `HttpClient` instance.

You will pass your Havalo API access key and secret to the `HavaloClient` via its constructor.  The `HavaloClient` instance will handle all authentication with the API on your behalf.  Further, you'll need to provide the Havalo API endpoint URL.

Note, the API key and secret are created by the Havalo API when a new repository is created.

```java
import com.kolich.havalo.client.service.HavaloClient;
import java.util.UUID;

// Your Havalo API key
final UUID key = ...;

// Your Havalo API secret
final String secret = ...;

// Your Havalo API endpoint URL, usually something like
// http://localhost:8080/havalo/api
final String apiUrl = ...;

final HavaloClient client = new HavaloClient(key, secret, apiUrl);
```

If you have a configured `HttpClient` that you'd like to use instead of the default, you can of course use a slightly different constructor and pass your own.

```java
import org.apache.http.client.HttpClient;

final HttpClient httpClient = ...; // Your own HttpClient instance

final HavaloClient client = new HavaloClient(httpClient, key, secret, apiUrl);
```

Finally, if you're using Spring, your web-application can also instantiate a `HavaloClient` bean.

```xml
<!-- An HttpClient instance, either created by the KolichHttpClientFactory or on your own. -->
<bean id="YourHttpClient"
  class="com.kolich.http.blocking.KolichDefaultHttpClient.KolichHttpClientFactory"
  factory-method="getNewInstanceWithProxySelector">
  <constructor-arg><value>Some kewl user-agent</value></constructor-arg>
</bean>

<bean id="HavaloClient"
  class="com.kolich.havalo.client.service.HavaloClient">
  <constructor-arg index="0" ref="YourHttpClient" />
  <constructor-arg index="1"><value>6fe8e625-ec21-4890-a685-a7db4346cceb</value></constructor-arg>
  <constructor-arg index="2"><value>Crb7s5coXNb...EnQIYr-9cxNqShozksHitLg</value></constructor-arg>
  <constructor-arg index="3"><value>http://localhost:8080/havalo/api</value></constructor-arg>
</bean>
```

That's it, you're ready to make API requests.

  For more details on this return type and how to use it, please refer to the Functional Concepts overview in my kolich-httpclient4-closure library.

#### authenticate()

Verify your Havalo API authentication credentials.

Does nothing other than verifies your API key and secret.  This is most useful on application startup when you want to verify connectivity/access to the Havalo API before attempting to do actual work.

```java
final Either<HttpFailure,KeyPair> auth =
  client.authenticate();

if(auth.success()) {
  // Success
} else {
  // Failed
}
```

#### createRepository()

Create a new repository.

Note that only **administrator** level API users can create new repositories.

```java
final Either<HttpFailure,KeyPair> repo =
  client.createRepository();

final KeyPair kp;
if((kp = repo.right()) != null) {
  // Success
  System.out.println("Your new API key: " + kp.getKey());
  System.out.println("Your new API secret: " + kp.getSecret());
}
```

#### deleteRepository(toDelete)

Delete repository by UUID `toDelete`.

Note that only **administrator** level API users can delete repositories.

```java
final UUID toDelete = ...; // The UUID of the repository to delete.

final Either<HttpFailure,Integer> del =
  client.deleteRepository(toDelete);

if(del.success()) {
  System.out.println("Deleted repository successfully, status code: " +
    del.right());
}
```

#### listObjects([prefix...])

List objects in repository, or list all objects in repository that start with a given prefix.

Note the `prefix` argument is optional — if omitted all objects will be returned.

```java
// List all objects whose key starts with "foobar/baz"
final Either<HttpFailure,ObjectList> list =
  client.listObjects("foobar", "baz");

if(list.success()) {
  final ObjectList objs = list.right();
  System.out.println("Found " + objs.size() + " objects.");
}
```

#### getObject(outputStream, path...)

Get an object with the given `path` and write it out to the provided `outputStream`.

```java
final OutputStream os = ...; // An existing and open OutputStream.

// Get the object whose key is "foobar/baz/0.json" and stream its
// bytes to the provided OutputStream.
final Either<HttpFailure,List<Header>> get =
  client.getObject(os, "foobar", "baz", "0.json");

if(get.success()) {
  // Success, object data was copied to provided OutputStream.
  // Here are the HTTP headers on the response.
  final List<Header> headers = get.right();
  for(final Header h : headers) {
    System.out.println(h.getName() + ": " + h.getValue());
  }
} else {
  // Object not found.
}
```

Or, pass a `CustomEntityConverter` provided by the kolich-httpclient4-closure to stream the object "elsewhere" on success, or handle a failure on error.  This allows you to extract meta-data about the object from Havalo before streaming the object out to a consumer — properties like the HTTP `Content-Length` or `Content-Type` of the object are only available on a `GET` operation if you use a `CustomEntityConverter`.

```java
import com.kolich.http.blocking.helpers.definitions.CustomEntityConverter;

import org.apache.commons.io.IOUtils;

final ServletResponse response = ...; // From your Servlet container

client.getObject(new CustomEntityConverter<HttpFailure,Long>() {
  @Override
  public Long success(final HttpSuccess success) throws Exception {
    // Send down the HTTP Content-Type as fetched in the response
    // from the Havalo K,V store.
    final String contentType;
    if((contentType = success.getContentType()) != null) {
      response.setContentType(contentType);
    }
    // Send down the HTTP Content-Length as fetched in the response
    // from the Havalo K,V store.
    final String contentLength;
    if((contentLength = success.getContentLength()) != null) {
      response.setContentLength(Integer.parseInt(contentLength));
    }
    // Actually stream the bytes out to the caller.
    final ServletOutputStream os = response.getOutputStream();
    return IOUtils.copyLarge(success.getContent(), os);
  }
  @Override
  public HttpFailure failure(final HttpFailure failure) {
    // Handle failure, write out error response, do whatever is
    // appropriate on error.
    // ...
    return failure;
  }
}, "foobar", "baz", "0.json");
```

Or, even further, you can pass a `CustomSuccessEntityConverter<S>` and a `CustomFailureEntityConverter<F>` to define separate units of work to be "called" on either success or failure.

```java
import com.kolich.http.blocking.helpers.definitions.CustomFailureEntityConverter;
import com.kolich.http.blocking.helpers.definitions.CustomSuccessEntityConverter;

client.getObject(
  // Success converter
  new CustomSuccessEntityConverter<S>() {
    @Override
    public S success(final HttpSuccess success) throws Exception {
      // Do something on success, return type 'S'
    }
  },
  // Failure converter
  new CustomFailureEntityConverter<F>() {
    @Override
    public F failure(final HttpFailure failure) {
      // Do something on failure, return type 'F'
    }
  },
  // Path to object key
  "foobar", "baz", "0.json"
);
```

The intention of `CustomSuccessEntityConverter<S>` and `CustomFailureEntityConverter<F>` is to let you define reusable units of work — reusable implementations that define how to convert a response entity into something useful specific to your application, outside of an inline anonymous class.

#### getObjectMetaData(path...)

Get the meta data associated with the object at the given `path`.

Any HTTP headers sent with the object during a `PUT` are returned.  Note that the API generated SHA-1 hash that was computed on upload is also returned in the `ETag` HTTP response header.

```java
// Get the meta data for the object whose key is "foobar/baz/1.xml"
final Either<HttpFailure,List<Header>> meta =
  client.getObjectMetaData("foobar", "baz", "1.xml");

if(meta.success()) {
  final List<Header> headers = meta.right();
  for(final Header h : headers) {
    System.out.println(h.getName() + ": " + h.getValue());
  }
}
```

#### putObject(inputStream, contentLength, headers, path...)

Upload (`PUT`) an object to the given `path` that is `contentLength` bytes long, using the provided `inputStream`.  Send any additional meta data represented by `headers` with the request too.

```java
import static org.apache.http.HttpHeaders.CONTENT_TYPE;
import static org.apache.http.HttpHeaders.ETAG;

final InputStream is = ...; // An existing and open InputStream.

// Upload an object to path "baz/foobar.jpg" .. since it's a JPG
// image, also send the relevant Content-Type with the request.
final Either<HttpFailure,FileObject> upload =
  client.putObject(is,
    // The number of bytes in this object.
    1024L,
    // A Content-Type to be saved with the object.  This header is
    // sent back with the object when it's retrieved.
    new Header[]{new BasicHeader(CONTENT_TYPE, "image/jpeg")},
    // The path to the object.
    "baz", "foobar.jpg");

if(upload.success()) {
  // Success
  // The SHA-1 hash of the uploaded object can be found in the
  // ETag HTTP response header.
  final String hash = upload.right().getFirstHeader(ETAG);
  System.out.println("Uploaded object SHA-1 hash is: " + hash);
}
```

**TIP:** For a conditional `PUT`, you can also send an `If-Match` HTTP request header with your request.  If the SHA-1 hash sent with the `If-Match` header matches the current SHA-1 hash of the object, the object will be *replaced*.  If the SHA-1 hash sent with the `If-Match` header does *not* match the current hash of the object, the `PUT` will fail with a `409 Conflict`.

#### putObject(byte[], path...)

Upload (`PUT`) an object to the given `path` using the provided `byte[]` array.

```java
final byte[] data = ...; // Some byte[] array of data.

// Upload an object to path "cat"
final Either<HttpFailure,FileObject> upload =
  client.putObject(data, "cat");

if(upload.success()) {
  // Success
  // The SHA-1 hash of the uploaded object can be found in the
  // ETag HTTP response header.
  final String hash = upload.right().getFirstHeader("ETag");
  System.out.println("Uploaded object SHA-1 hash is: " + hash);
}
```

#### deleteObject(headers[], path...)

Delete an object at the given `path` only if the SHA-1 hash of that object matches the SHA-1 hash sent with the `If-Match` HTTP request header.

```java
import static org.apache.http.HttpHeaders.IF_MATCH;

// An SHA-1 hash for the version of the object you want to delete.
final String myHash = "de9f2c7fd25e1b3afad3e85a0bd17d9b100db4b3";

// Delete the object at path "foobar/cat" only if that object's hash
// equals "de9f2c7fd25e1b3afad3e85a0bd17d9b100db4b3".
final Either<HttpFailure,Integer> delete =
  client.deleteObject(
    new Header[]{new BasicHeader(IF_MATCH, myHash)},
    "foobar", "cat");

if(delete.success()) {
  // Success
} else {
  // Failed, get the resulting HTTP status code so
  // we can see what happened.
  switch(delete.left().getStatusCode()) {
    case 404:
      // 404 Not Found
      // Object at provided path didn't exist.
      // ...
      break;
    case 409:
      // 409 Conflict
      // Object conflict, the sent SHA-1 hash did not match.
      // ...
      break;
    default:
      // Hmm, something else went wrong.
      // ...
      break;
  }
}
```

#### deleteObject(path...)

Delete an object at the given `path`, ignoring the object's current hash.

```java
// Delete the object at path "foobar/cat".
final Either<HttpFailure,Integer> delete =
  client.deleteObject("foobar", "cat");

if(delete.success()) {
  // Success
} else {
  // Failed
  System.out.println("Oops, delete failed with status: " +
    delete.left().getStatusCode());
}
```

## Building

This Java library and its dependencies are built and managed using SBT.

To clone and build havalo-kvs-client, you must have SBT installed and configured on your computer.

The havalo-kvs-client SBT Build.scala file is highly customized to build and package this Java artifact.  It's written to manage all dependencies and versioning.

To build, clone the repository.

    #~> git clone git://github.com/markkolich/havalo-kvs-client.git

Run SBT from within havalo-kvs-client.

    #~> cd havalo-kvs-client
    #~/havalo-kvs-client> sbt
    ...
    havalo-kvs-client:1.4>

You will see a `havalo-kvs-client` SBT prompt once all dependencies are resolved and the project is loaded.

In SBT, run `package` to compile and package the JAR.

    havalo-kvs-client:1.4> package
    [info] Compiling 12 Java sources to ~/havalo-kvs-client/target/classes...
    [info] Packaging ~/havalo-kvs-client/dist/havalo-kvs-client-1.4.jar ...
    [info] Done packaging.
    [success] Total time: 4 s, completed

Note the resulting JAR is placed into the **havalo-kvs-client/dist** directory.

To create an Eclipse Java project for havalo-kvs-client, run `eclipse` in SBT.

    havalo-kvs-client:1.4> eclipse
    ...
    [info] Successfully created Eclipse project files for project(s):
    [info] havalo-kvs-client

You'll now have a real Eclipse **.project** file worthy of an Eclipse import.

Note your new **.classpath** file as well — all source JAR's are fetched and injected into the Eclipse project automatically.

## Licensing

Copyright (c) 2014 Mark S. Kolich

All code in this artifact is freely available for use and redistribution under the MIT License.

See LICENSE for details.

repository: markkolich/havalo-kvs-client

repo_name: markkolich/havalo-kvs-client


text:
# Work with plugins

 What is plug-in?

you can add plugin in folder config/plugins

 Start Work 🔘

$RamiP = new ASA_plugins(array filenames = []);

 Examples :

$RamiP = new ASA_plugins(['functions.php','config.php']);

 Load Folder plugin 👇

$RamiP->PluginLoad($folder, $file);

 A guide to working with the above function 👇

 What is $folder ?

 Enter the folder name in which you have the plugin 😎👌

 What is $file ?

 The original file name that attaches to other items in the folder (main file this plugin) ❇

 Direct connection to GitHab 👇

$RamiP->github($username, $repository, $plugin);

 What is $plugin ? github("KyleAMathews","phpmailer","class.phpmailer.php");

 for install and include phpmailer


text:
# Chirpy Starter [![Gem Version](https://img.shields.io/gem/v/jekyll-theme-chirpy)](https://rubygems.org/gems/jekyll-theme-chirpy) [![GitHub license](https://img.shields.io/github/license/cotes2020/chirpy-starter.svg?color=blue)][mit]

The startup template for [**Jekyll Theme Chirpy**][chirpy].

When installing the **Chirpy** theme through [RubyGems][gem], Jekyll can only read files in the folders `_includes`, `_layout`, `_sass` and `assets`, as well as a small part of options of the `_config.yml` file from the theme's gem. (You can find the gem files by using the command `bundle info --path jekyll-theme-chirpy`). To fully use all the features of **Chirpy**, you need to copy the other critical files/directories from the theme's gem to your Jekyll site.

The critical files/directories to run or build the **Chirpy** theme are as follows:

```shell
.
├── _data
├── _plugins
├── _tabs
├── _config.yml
└──  index.html
```

So we've extracted all the **Chirpy** gem necessary content here to help you get started quickly.

## Installation

[Use this template][usetemplate] to generate a new repository, and then execute:

[usetemplate]: https://github.com/cotes2020/chirpy-starter/generate

```
$ bundle
```

## Usage

Please see the [theme's docs](https://github.com/cotes2020/jekyll-theme-chirpy#usage).

## Upgrading

First, please modify the target version number of `jekyll-theme-chirpy` in the `Gemfile` (e.g., `gem "jekyll-theme-chirpy", "~> 4.0", ">= 4.0.1"`).

After that, execute the following command:

```console
$ bundle update jekyll-theme-chirpy
```

As the version upgrades, the critical files and configuration options will change. Please refer to the [Upgrade Guide](https://github.com/cotes2020/jekyll-theme-chirpy/wiki/Upgrade-Guide) to keep your website files in sync with the latest version of the theme.

## License

This work is published under [MIT][mit] License.

[gem]: https://rubygems.org/gems/jekyll-theme-chirpy
[chirpy]: https://github.com/cotes2020/jekyll-theme-chirpy/
[mit]: https://github.com/cotes2020/chirpy-starter/blob/master/LICENSE

gha_language: Shell


text:
# StatsD
A simple protocol and daemon to aggregate and summarize application metrics
- applications have a client (language specific library) that communicate with the StatsD daemon, which generates metrics and relays them to a monitoring backend
- the StatsD client library sends individual calls to the StatsD server over a UDP datagram (UDP, no acknoledgement, no library blocking when submitting data)
  - doesn't buffer data between calls to the server, so less complexity
- the StatsD daemon listens to UDP traffic from all applcation libraries and aggregates data over time, and flushing it to the data backend on defined intervals
- the monitoring backend turns metrics into usable charts and alerts (Datadog)
- StatsD offers more simplicity over other methods, by decoupling the application from its instrumentation (StatsD won't crash your app)